On Fri, Jul 24, 2009 at 9:34 AM, Ola Bini <[email protected]> wrote:
> Subramanya Sastry wrote:
>
>>
>>
>> So, the real question here boils down to the previous one: can we safely
>> determine what local variables are captured by closures? In that sense,
>> this is not a new special case that we need
>>
> No, that's not really possible. Seeing as you can do something like this:
>
> def foo(n, x)
> proc do
> n + 1
> end
> end
>
> b = foo(42, "blarg")
>
> eval("puts x", b)
>
I should have rephrased as: "how much information can we infer about capture
of local variables?" because the safe thing to do is to always materialize a
method scope as a frame. With procs, given that ruby defines them to have
access to the variables of its scope, the correct and safest thing to do is
materialize the enclosing scope (with all its local variables) as a heap
frame.
So, in this example, as you indicate, it is not possible to infer much about
'x' even though x is not used in the proc body itself. Even if the eval
didn't use 'x' we would still have to store x in the frame. This is
"conservative" since most uses of proc won't "directly" know which other
variables are accessible. But, given how much mileage Rails has derived by
using conventions to pass around implicit information like this ("if you use
the Rails convention of naming your variable 'x', you will see magic happen
elsewhere"), I wouldn't be surprised if this was more commonly used than it
seems. The only way out of this predicament is if we knew all the use sites
of a proc. Since procs usually get passed as arguments to a method, that is
usually very hard to do.
Besides procs, binding, (and lambda which are basically procs), are there
other situations that force all variables to be stored in frames?
For "regular" closures (those that dont use escape hatches like eval), we
can identify captured variables fairly accurately it seems to me.
Subbu.