The original address: gbracha.blogspot.com/2012/07/see…

Gbracha.blogspot.com/

Published: July 23, 2012

I’ve discussed mirror-based reflection many times in past blogs and lectures. And I’m not the only one — you can read Alan Wirf-Brock’s post on mirrors in Javascript. In this article, I want to focus on a particular kind of mirror that doesn’t get a lot of attention. Before I dive into the details, a little background.

You can’t understand the internal structure of a function: you can only apply it to various parameters and see how it reacts. This is sometimes called procedural abstraction. In other ways, it is the foundation for object-based encapsulation.

Most languages that call themselves object-oriented don’t actually support object-based encapsulation. Despite this flaw, one of their approaches is to rely directly on procedural abstractions. Perhaps the most obvious example of this is Javascript. The only way to encapsulate anything in Javascript is to put it in a function. Well-designed patterns leverage Javascript closures to provide encapsulation.

As you can see from above, procedural abstraction is the absolute foundation. In some cases, we may still want to break through procedural abstractions.

Consider implementing a database interface in the style of LINQ, Ruby on Rails or Glorp. The underlying model is that the database consists of collections that are accessed through standard functional operations such as Filter, Map, Reduce, and so on. The parameters for these operations include closures. For example, you can write a query such as.

cities.filter(function(city){returnCity. The name = 'Paris'; });Copy the code

And a collection of answers that included Paris, Texas, and a few other cities. To implement this interface on a database, you might want to convert this code into an SQL query. To do this, you need to understand what closures do. For example, in.NET, the type system is designed to force literal closures into abstract syntax trees representing their internal expressions, which can then be compiled into SQL.

Of course, you may not be able to compile your code into SQL queries properly at all. We’ll assume that the system is allowed to fail in any situation it deems too difficult, but we want to handle as many situations as possible.

LINQ’s methods rely on static typing, but this is not necessary and in fact has drawbacks. For example, static methods exclude the following.

query(f) {returncities.filter(f); }Copy the code

A more common option is to derive the AST of the closure dynamically. Anyway, I seem to need a way to get the AST (or at least the source) of the closure — procedural abstraction is, of course, to rule this out.

Even if I could get the source code or AST, it might not be enough. Let’s say I want to write

varCityNames = [' Paris', 'London', 'New York']; cities.filter(function(city){return cityNames.contains(city.name)
});
Copy the code

I need the value of cityNames in order to execute the query. In general, I need to get the scope of the closure in execution.

Smalltalk and its relatives allow you to do this. How do they get around procedural abstractions? Well, in terms of closures, they basically throw procedural abstraction out the door. Every Smalltalk closure will happily provide you with its context, which is a unified scope that allows you to find all the variables used in the closure.

Obviously, this is not a very safe solution. We can often reconcile security and reflection with mirroring, which is the focus of this article. Given a mirror image of an object that has full access to the closure object representation, you should be able to get all the information you need. This still has the disadvantage that the closure representation is exposed as a public API.

In this case, we need a ClosureMirror. Essentially, you need an object with the magical ability to observe closures and overcome procedural abstractions. Closures themselves do not allow this; It has to be impenetrable. The ability to look inside must be a separate object that can be distributed or withheld independently (exercise for the reader: Find another way to solve this problem).

In particular, ClosureMirror needs to be able to provide source code for the closure it reflects and a mapping from identifiers to values that describes the closure’s current scope.

Another case where closure images come in handy is serialization. If you need to serialize an object containing a closure, you also need to access the scope of the closure.

I don’t see any discussion of closed mirrors anywhere else. As far as I know, the only implementation is as part of the Newspeak to Javascript compiler. We’re also considering implementing it in the context of the Dart mirror system. Newspeak-on-javascript’s implementation of closed mirroring is quite naive and inefficient. One reason for this inefficiency is that Javascript doesn’t provide any support to do this kind of thing. In any case, the idea is new and almost untested, but I think it has potential.

Posted by Gilad Bracha at 10:17 PM. News language, reflection


www.deepl.com translation