Rod Adams <[EMAIL PROTECTED]> writes: > Piers Cawley wrote: > >>Chip and I have been having a discussion. I want to write: >> >> sub foo { my $x = 1; return sub { eval $^codestring } } >> say foo()("$x"); >> >>I claim that that should print 1. Chip claims it should throw a warning about >>because of timely destruction. My claim is that a closure should close over >>the >>entire lexical stack, and not simply those things it uses statically. Chip >>claims the opposite, arguing that timely destruction implies that this is >>absolutely the right thing to do. It's also quicker. >> >> > I'm going to have to side with Piers on this one. My feeling is that having a > reference to a closure accessible in memory should keep all the possible > lexicals it can access in memory as well. That said, I can the compiler > optimizing memory consumption by destroying all the outer lexicals that it can > prove will never be used by the inner closure. However, the presence of an > eval' in the closure makes such a proof tenuous at best. > > On the other hand, one could easily view the eval as constructing yet another > closure, and it's unclear if we wish for that closure to be able to "skip" the > first level outer closure to directly access the 2nd level outer lexicals. In > that respect, I could see things Chip's way. > > As for the warning, it should only be a warning if strictures are on, for > using > the now undeclared '$x' inside the eval. > >>But dammit, I'm doing runtime evaluation of code strings, I don't care about >>quicker. >> >>If it's not the default can it please be mandated that there be some way of >>doing: >> >> sub foo { my $x = 1; return sub is lexically_greedy {eval $^codestring} } >> >>in other words, some way of declaring that a subroutine wants to hang onto >>every lexical it can see in its lexical stack, not matter what static analysis >>may say. >> >> >> > Well, you could always do something like: > > sub foo { my $x = 1; return sub {my $x := $OUTER::x; eval $^codestring} } > > But I'm spending too much time in other languages lately to remember exactly > how "$OUTER::x" is spelled for certain. One could probably even write a macro > that auto-binds all the lexicals in the outer scope to the current scope.
Only if I actually know what variables which were within scope when that inner sub was compiled are going to be used by my passed in code string. I really don't want to have to write a macro to walk the OUTER:: chain in order to build a something like: sub { my $foo = $OUTER::foo; my $bar = $OUTER::OUTER::bar; ...; eval $^codestring } Just to pull everything into scope. And even if I could do that, what I actually want to be able to do is something like this: $continuation.bindings.eval_in_this_scope($^codestring); Which can be done today in Ruby and which is one of the enabling technologies for tools like Rails.