On Mon, Aug 01, 2005 at 02:06:28AM +0800, Autrijus Tang wrote:
: Pugs did not support inline variable declarations, largely because the problem
: caused by this construct:
: 
:     {
:       say "values of β will give rise to dom!";
:       $x = $x + my $x if $x;
:       #1   #2      #3    #4
:     }
: 
: The evaluation order for the four $x is (#4, #2, #3, #1). However, because
: $Larry made it very clear that lexical scopes are lexical, (#1, #2) must refer
: to the same (outer) $x, and (#3, #4) refers to the inner $x. When implemented
: naively, this creates fragmented scopes in the PIL tree.
: 
: To simplify code generation, I propose that we float all lexical declarations
: in a scope to the top of the scope, in the same place as its formal
: parameters.  Of course, we will still reject bogus programs like this:
: 
:     # No previous $x available here
:     { say $x; my $x; }
: 
: But that means these now raises the same exception:
: 
:     sub f ($x) { my $x }
:     sub f { my $x; my $x }
: 
: Alternatively, this could raise a warning and treat the second my()
: as a no-op.  Personally, I'm in favour of an exception.

I think the exception should certainly be the default, perhaps with
the other behavior pragmatically available.  But we're trying to get
people to switch from = to -> anyway, and most of the places people
want repeated "my" are in repeated conditionals:

    if my $x = foo() {...}
    if my $x = bar() {...}
    if my $x = baz() {...}

So that sort of thing is likely to occur in a larger scope that is amenable
to pragma.  Interestingly, the "my" is actually required at the moment
because we've said that assignment to an *existing* variable in a boolean
context is illegal:

    if $x = foo() {...} # ERROR
    if $x = bar() {...} # ERROR
    if $x = baz() {...} # ERROR

That's also to encourage people to write:

    if foo() -> $x {...}
    if bar() -> $x {...}
    if baz() -> $x {...}

if that's what they mean.  (And, of course, to catch the recurrent =/==
error we inherited from C.)

: Under this scheme, the compiler will mark variable lookups to the outer
: scope explicit.  The sample construct at the beginning of this post will
: get compiled to this form, leaving the evaluation order explicit:
: 
:     CODE(
:         syms => [$x],
:         body => [
:             SAY("values of β will give rise to dom!"),
:             IF(
:                 cond => $x,
:                 body => ASSIGN(
:                     from => ADD(
:                         l => $OUTER::x,
:                         r => $x,
:                     ),
:                     into => $OUTER::x
:                 )
:             );
:         ]
:     );
: 
: The only problem I see with it is that $CALLER::x from &ADD's position
: will refer to the inner, not the outer, $x.

A similar problem pops up for "eval" as well, though arguably it is the
same problem if the compiler is using the CALLER mechanism to lookup
variables.

: However, seeing that the two
: arguments are in different scopes, I think it is not worth keeping any promise
: about interaction between $CALLER:: and mid-block declarations anyway.  
: 
: Does this sound sane?

We can certainly declare it to be sane.  :-)

Or perhaps we can reserve judgement on that, and merely declare that
it is insane (read: erroneous) to request variable lookup on $x from a
text where it's ambiguous whether it refers to outer $x or later $x.
Then we could someday do the fancy thing and resolve the ambiguity
based on the (remembered) location of the eval/call itself, whereupon
the blame for all the suddenly broken code will naturally slide off of
our teflon-coated exteriors.

Alternately, we could do the fancy thing now and just remember the actual
limits of the variables' visibility.  But only if it's fun.  :-)

Larry

Reply via email to