perl11 / cperl

A perl5 with classes, types, compilable, company friendly, security
http://perl11.org/
Other
142 stars 17 forks source link

hash slice autovivify #347

Closed rurban closed 6 years ago

rurban commented 6 years ago

hash slices autovivify if used as sub args or as for lists. This is a bug, not a feature. single hash elements do not autovivify, and unrolled loops neither. See https://rt.perl.org//Public/Bug/Display.html?id=2166 At least add a warning until it is fixed. Yes, hslices are useful sometimes. But still broken. The best fix is to assign to a temp array, and use this for loops and sub args. This is the best portable way.

my %h; foreach (@h{a, b}) {} keys %h => 2

sub foo {}; foo($h{a}, @h{"b", "c"}); keys %h => 2

I found no single instance in any core or CPAN module where it was abused as feature, i.e. that the keys should be vivified within or after sub args or loops.

Occurences:

non-core:

See the bugfix/gh347-hslice branch See also http://consttype.blogspot.de/2009/03/autovivification-in-perl-5.html

rurban commented 6 years ago

Fixed with a new STACKCOPY private bit for hslice, which copies the hash value on the stack. Used with subs args and for loop lists. In core this was used: ++$_ for @INC{"charnames.pm","_charnames.pm"}

rurban commented 6 years ago

Fixed with a7c61ac1b8d5353eab697a4301fb302e9bcbf5d8

rurban commented 6 years ago

Wrong. Ultimately hslices should work exactly as the expanded list of helem's. helem's do autovivify on for loops. There's no copy. cperl -e'my %h; for ($h{'a'}, $h{'b'}) {}; print keys %h' => 2 so for (@h{qw(a b)}) {} should do the same.

Same for %h{qw(a b)} kvhslices. There the key is always copied in lvalue context, the value same as in hslice.

It either returns the hash element directly or a copy of it. with loops it should do no copying, with subs it should.