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

map sometimes does and sometime does not copy vals #15590

Open
p5pRT opened this issue Sep 6, 2016 · 4 comments
Open

map sometimes does and sometime does not copy vals #15590

p5pRT opened this issue Sep 6, 2016 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 6, 2016

Migrated from rt.perl.org#129208 (status was 'open')

Searchable as RT129208$

@p5pRT
Copy link
Author

p5pRT commented Sep 6, 2016

From @cpansprout

I would expect these two to be equivalent​:

$ ./perl -Ilib -le '$x = 4; sub {\@​_; for (map {$_[0]} 1) { $_=3 } }->($x); print $x'
4
$ ./perl -Ilib -le '$x = 4; sub {\@​_; for (map {shift} 1) { $_=3 } }->($x); print $x'
3

This is with v5.25.4-89-g05bda26, but the behaviour is ancient. I get the same results with 5.8.7.

Depending on internal flags, map may or may not copy the value returned from the block.

I believe it should always copy, but I wanted to check to make sure before making the change.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Sep 6, 2016

From zefram@fysh.org

Father Chrysostomos wrote​:

I would expect these two to be equivalent​:

$ ./perl -Ilib -le '$x = 4; sub {\@​_; for (map {$_[0]} 1) { $_=3 } }->($x); print $x'
4
$ ./perl -Ilib -le '$x = 4; sub {\@​_; for (map {shift} 1) { $_=3 } }->($x); print $x'
3

Not sure why you'd expect them to be equivalent. You're basically asking
for $_[0] and shift to be equivalent in whether they yield an lvalue.
Which they're not​:

$ perl -lwe '$x = 4; sub { $_[0] = 3; }->($x); print $x'
3
$ perl -lwe '$x = 4; sub { shift = 3; }->($x); print $x'
Can't modify shift in scalar assignment at -e line 1, near "3;"
Execution of -e aborted due to compilation errors.

However, these two methods of using $_[0]/shift disagree on which one
yields an lvalue. Furthermore, shift yields something lvalue enough to
get an equivalence out of it​:

$ perl -lwe '$x = 4; sub { ${\shift} = 3; }->($x); print $x'
3
$ perl -le '$x = 4; sub {\@​_; for (map {${\shift}} 1) { $_=3 } }->($x); print $x'
4

Then there's a third obvious way of using the maybe-lvalue that yields
different results again​:

$ perl -lwe '$x = 4; sub { for($_[0]) { $_ = 3; } }->($x); print $x'
3
$ perl -lwe '$x = 4; sub { for(shift) { $_ = 3; } }->($x); print $x'
3
$ perl -lwe '$x = 4; sub { for(${\shift}) { $_ = 3; } }->($x); print $x'
3

So it's consistently inconsistent.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Sep 6, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Sep 6, 2016

From @cpansprout

On Mon Sep 05 23​:05​:36 2016, zefram@​fysh.org wrote​:

Father Chrysostomos wrote​:

I would expect these two to be equivalent​:

$ ./perl -Ilib -le '$x = 4; sub {\@​_; for (map {$_[0]} 1) { $_=3 } }-

($x); print $x'
4
$ ./perl -Ilib -le '$x = 4; sub {\@​_; for (map {shift} 1) { $_=3 } }-
($x); print $x'
3

Not sure why you'd expect them to be equivalent. You're basically
asking
for $_[0] and shift to be equivalent in whether they yield an lvalue.
Which they're not​:

$ perl -lwe '$x = 4; sub { $_[0] = 3; }->($x); print $x'
3
$ perl -lwe '$x = 4; sub { shift = 3; }->($x); print $x'
Can't modify shift in scalar assignment at -e line 1, near "3;"
Execution of -e aborted due to compilation errors.

They are equivalent in that they return values that are referentially identical, such that \$_[0] == \shift.

However, these two methods of using $_[0]/shift disagree on which one
yields an lvalue. Furthermore, shift yields something lvalue enough
to
get an equivalence out of it​:

$ perl -lwe '$x = 4; sub { ${\shift} = 3; }->($x); print $x'
3
$ perl -le '$x = 4; sub {\@​_; for (map {${\shift}} 1) { $_=3 } }-

($x); print $x'
4

The equivalence is what I’m looking for.

Either map’s return value should be referentially identical to the value returned from the block, or it should not be. map should be consistent either way. Make sense?

(Fixing this is just a matter of checking that the refcount is 1 before deciding to skip copying something already marked SvTEMP.)

Then there's a third obvious way of using the maybe-lvalue that yields
different results again​:

$ perl -lwe '$x = 4; sub { for($_[0]) { $_ = 3; } }->($x); print $x'
3
$ perl -lwe '$x = 4; sub { for(shift) { $_ = 3; } }->($x); print $x'
3
$ perl -lwe '$x = 4; sub { for(${\shift}) { $_ = 3; } }->($x); print
$x'
3

So it's consistently inconsistent.

And the fact the the AvREAL flag on @​_ makes a difference is a bug, too.

--

Father Chrysostomos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants