Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

The old "$x will not stay shared" thing.

0 views
Skip to first unread message

Audrey Tang

unread,
Jan 16, 2006, 1:38:14 AM1/16/06
to Perl 6 Language
-----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.

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?
* Does it make sense to change the undecorated "sub g"'s behaviour to
match "our sub g"?
* 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)?

I'd be happy to patch S06 when we get a consensus/ruling this time. :-)

Thanks,
Audrey
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (FreeBSD)

iD8DBQFDyz9WtLPdNzw1AaARApSXAKCrjk4dxDPhj7or2qxJBlULVBXgEQCfZxLO
kza0/2Xv3iAGXNaaw73phyw=
=rAZq
-----END PGP SIGNATURE-----

Larry Wall

unread,
Jan 16, 2006, 6:41:06 PM1/16/06
to Perl 6 Language
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

Rob Kinyon

unread,
Jan 16, 2006, 9:56:50 PM1/16/06
to Perl 6 Language
On 1/16/06, Larry Wall <la...@wall.org> 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

0 new messages