Re: The old $x will not stay shared thing.

2006-01-16 Thread Larry Wall
On Mon, Jan 16, 2006 at 02:38:14PM +0800, Audrey Tang wrote:
: -BEGIN PGP SIGNED MESSAGE-
: Hash: SHA1
: 
: I'm almost sure this had been covered before, but I failed to find a
: reference in either the archives or in synopses, so here goes again:
: 
: sub f ($x) {
: sub g ($y) { $x + $y }; g($x);
: }
: f(10); # 20?
: 
: Currently in Pugs, g is built at BEGIN time when f had not finished
: building up its lexical environment, and as such fails to see the
: runtime $x. The desugared form is:
: 
: our g;
: BEGIN { g := sub ($y) { $x + $y } }
: 
: However, the following form does work in the Parrot, JavaScript and
: Haskell runcore:
: 
: sub f ($x) {
: my sub g ($y) { $x + $y }; g($x);
: }
: 
: the reason it works is that g's body is replaced every time upon f's
: entry.  This is probably the expected behaviour.

Yup.

: What would happen for the our sub g form, where it becomes possible to
: call g directly without entering f?  This shows Pugs's current behaviour:
: 
: sub f ($x) {
: our sub g ($y) { $x + $y }; g($x);
: }
: f(10); # 20 for sure
: our g; # gets visibility to g
: g(100); # 110 this time?
: 
: So my questions are:
: 
: * Is the treatment above sane?

I think so, under the theory that g is just a persistent form of the
closure that happens to be cached in the symbol table rather than
in some $ref variable.  Though I can see temp our g being put
to interesting uses if g is getting arbitrarily rebound at various
points whenever f is called...

: * Does it make sense to change the undecorated sub g's behaviour to
: match our sub g?

Yes, at least for any block that really is capturing a closure.
Perhaps we need to distinguish those from accidentally nested
top-level functions.  But undecorated sub is more-or-less defined
to be our sub anyway, just as with package, module, and class
these days.  The only difference is that our explicitly introduces
a lexically scoped alias, while the undecorated form presumably doesn't.
Though we could break that too, I suppose.

: * If we insert a call to g() above without calling f() first, should it
: assume an uninitialized $x, or throw an exception (Pugs currently does
: the latter)?

An exception is fine, modulo what I said about accidental nesting.
When do you detect the condition?  If the inner function can't
reference $x, does it still fail?  On the other hand, we can get into
eval issues where it might or might not reference $x.  I'm okay
with requiring lexical scopes to have some existing relationship
with dynamic scopes, especially when we know some initialization is
required.

Larry


Re: The old $x will not stay shared thing.

2006-01-16 Thread Rob Kinyon
On 1/16/06, Larry Wall [EMAIL PROTECTED] wrote:
 Yes, at least for any block that really is capturing a closure.
 Perhaps we need to distinguish those from accidentally nested
 top-level functions.  But undecorated sub is more-or-less defined
 to be our sub anyway, just as with package, module, and class
 these days.  The only difference is that our explicitly introduces
 a lexically scoped alias, while the undecorated form presumably doesn't.
 Though we could break that too, I suppose.

What is the benefit for -not- explicitly introducing a lexically
scoped alias? Is there some performance reason why the undecorated
form wouldn't?

 : * If we insert a call to g() above without calling f() first, should it
 : assume an uninitialized $x, or throw an exception (Pugs currently does
 : the latter)?

 An exception is fine, modulo what I said about accidental nesting.
 When do you detect the condition?  If the inner function can't
 reference $x, does it still fail?  On the other hand, we can get into
 eval issues where it might or might not reference $x.  I'm okay
 with requiring lexical scopes to have some existing relationship
 with dynamic scopes, especially when we know some initialization is
 required.

What other forms would be useful other than our sub g {...}? If
they're useful, shouldn't they have keywords?

Rob