stevan / p5-mop-redux

A(nother) MOP for Perl 5
139 stars 36 forks source link

Can't close over attribute #86

Closed latk closed 10 years ago

latk commented 10 years ago

Given the simple class

class Foo {
  has $!attr = 0;
  method make_closure {
    return sub { say ++$!attr }
  }
}

I would expect the code

$c1 = Foo->new->make_closure;
$c2 = Foo->new->make_closure;
&$c1; &$c2; &$c1;

to output 1 1 2. However, we get 1 2 3 and a load of errors, because $instance is undef at line 90 of attribute.pm.

The invocant which the anonymous sub has closed over is not available in the dynamic scope of the $c1 invocation, therefore attribute lookup does not seem to work.

doy commented 10 years ago

For context:

$ perl6 -e'class Foo { has $!foo = 10; method close_over_foo { return sub { ++$!foo } } }; my $foo = Foo.new; my $closure = $foo.close_over_foo; say $closure.(); say $closure.(); my $foo2 = Foo.new; my $closure2 = $foo2.close_over_foo; say $closure2.(); say $closure2.()'
11
12
11
12

Also, even if we can't get this to work in the prototype, we should definitely not allow undef to be used as the instance when looking up attribute values - this should either do the right thing or die.

doy commented 10 years ago

That previous p6 snippet wasn't actually demonstrating the correct code, it should actually be this:

$ perl6 -e'class Foo { has $!foo = 10; method close_over_foo { return sub { ++$!foo } } }; my $closure = Foo.new.close_over_foo; say $closure.(); say $closure.(); my $closure2 = Foo.new.close_over_foo; say $closure2.(); say $closure2.()'
11
12
11
12