Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WhateverCode subscript inside WhateverCode inside block doesn't properly close over lexical #6098

Closed
p6rt opened this issue Feb 25, 2017 · 6 comments
Labels

Comments

@p6rt
Copy link

p6rt commented Feb 25, 2017

Migrated from rt.perl.org#130859 (status was 'resolved')

Searchable as RT130859$

@p6rt
Copy link
Author

p6rt commented Feb 25, 2017

From @smls

A WhateverCode containing an array subscript that is itself a
WhateverCode, usually works fine... e.g. `*.[*-1]` always returns the
last positional element of its argument.

A WhateverCode closing over a lexical variable usually works fine,
e.g. `* - $x` always subtracts the *current* value of $x from its
argument.

But when *both* of those features are combined, *and* the variable
that is closed over is scoped to an outer block or routine that is
called repeatedly, then it misbehaves​:

  sub f { my $x = ++$; (*.[* - $x])(<a b c>) }
  say (f,f,f); # (c c c)

The same, using `map`​:

  say (1..3).map​: { (*.[* - $_])(<a b c>) }; # (c c c)

The expected output would be `(c b a)`. For some reason, it seems to
use the first value of `$x` or `$_` for all three iterations.


Demonstration that the particular circumstances described above have
to align for the bug to appear​:

1) If the WhateverCode subscript is replaced with a static expression,
the bug disappears​:

  say (1..3).map​: { (*.[3 - $_])(<a b c>) }; # (c b a)

2) If the outer WhateverCode is removed by "inlining" it, the bug disappears​:

  say (1..3).map​: { <a b c>[* - $_] }; # (c b a)

3) If the `map` is unrolled so that there is no outer block that gets
re-entered between invocations of the WhateverCode's, the bug
disappears​:

  my &f = *.[* - $_];
  $_ = 1; say f <a b c>; # c
  $_ = 2; say f <a b c>; # b
  $_ = 3; say f <a b c>; # a


This is Rakudo version 2017.02-95-g0be724727 built on MoarVM version
2017.02-7-g3d859008 implementing Perl 6.c.

@p6rt
Copy link
Author

p6rt commented Feb 27, 2017

From @smls

Replacing the outer WhateverCode with a Block lambda, makes the bug disappear​:

  say (1..3).map​: -> $n { {.[* - $n]}(<a b c>) }; # (c b a)

Replacing the WhateverCode subscript with a Block lambda subscript, makes the bug disappear​:

  say (1..3).map​: -> $n { (*.[{$_ - $n}])(<a b c>) }; # (c b a)

@p6rt
Copy link
Author

p6rt commented Feb 27, 2017

From @smls

committable reveals that the bug has existed since before 2014.01​: https://gist.github.com/Whateverable/3ccc9613317d5d5241021431e8e525bb

@p6rt
Copy link
Author

p6rt commented Feb 5, 2018

From @zoffixznet

On Sat, 25 Feb 2017 06​:55​:02 -0800, smls75@​gmail.com wrote​:

A WhateverCode containing an array subscript that is itself a
WhateverCode, usually works fine... e.g. `*.[*-1]` always returns the
last positional element of its argument.

A WhateverCode closing over a lexical variable usually works fine,
e.g. `* - $x` always subtracts the *current* value of $x from its
argument.

But when *both* of those features are combined, *and* the variable
that is closed over is scoped to an outer block or routine that is
called repeatedly, then it misbehaves​:

sub f { my $x = ++$; (*.[* - $x])(<a b c>) }
say (f,f,f); # (c c c)

The same, using `map`​:

say (1..3).map​: { (*.[* - $_])(<a b c>) }; # (c c c)

The expected output would be `(c b a)`. For some reason, it seems to
use the first value of `$x` or `$_` for all three iterations.

----------

Demonstration that the particular circumstances described above have
to align for the bug to appear​:

1) If the WhateverCode subscript is replaced with a static expression,
the bug disappears​:

say (1..3).map​: { (*.[3 - $_])(<a b c>) }; # (c b a)

2) If the outer WhateverCode is removed by "inlining" it, the bug
disappears​:

say (1..3).map​: { <a b c>[* - $_] }; # (c b a)

3) If the `map` is unrolled so that there is no outer block that gets
re-entered between invocations of the WhateverCode's, the bug
disappears​:

my &f = *.[* - $_];
$_ = 1; say f <a b c>; # c
$_ = 2; say f <a b c>; # b
$_ = 3; say f <a b c>; # a

----------
This is Rakudo version 2017.02-95-g0be724727 built on MoarVM version
2017.02-7-g3d859008 implementing Perl 6.c.

Thank you for the report. This is now fixed.

Fix​: rakudo/rakudo@e8c6c259ce72fb5
Test​: Raku/roast@501f51b56c77fec06

@p6rt
Copy link
Author

p6rt commented Feb 5, 2018

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Feb 5, 2018

@zoffixznet - Status changed from 'open' to 'resolved'

@p6rt p6rt closed this as completed Feb 5, 2018
@p6rt p6rt added the weird label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant