> fetched up front.
I'm confused, you just explained
> > 1) There's no copying, 2) it uses the built-in iterator.
Did you correct yourself or am I misunderstanding you?
FWIW: I'm installing 5.38.2 for testing via Perlbrew and it takes hours...
| [reply] |
It uses the built-in iterator to obtain the keys and values from the hash and push them unto the stack before any looping is performed.
If you want me to be more precise, no extra copying occurs.
- The keys are copied (i.e. fresh scalars are made for the keys) since they're not found as scalars in the hash. But that has to happen no matter the interface.
- The pointers to the scalars placed on the stack. But that has to happen no matter the interface.
$ perl -e'
use v5.14;
use experimental qw( for_list );
my %h = ( a => 4, b => 6 );
my $i = 0;
for my ( $k, $v ) ( %h ) {
if ( !$i++ ) { ++$h{a}; ++$h{b}; }
say "$k:$v";
}
'
a:5
b:7
| [reply] [d/l] |
- The pointers to the scalars placed on the stack. But that has to happen no matter the interface.
I believe LanX's performance concern is whether a hash with 100,000 elements must extend the perl stack to 200,000 elements before beginning the loop. It's not a guaranteed implementation detail since, as I recall, for (1..100_000) is optimized to use a counter and repeatedly modify a scalar rather than generating 100_000 distinct scalars at once.
So I think I'm hearing that yes it does need to allocate the perl stack to 200_000 elements, and does not perform some fancy optimized use of 'each'.
Also I would not say that "it uses the built-in iterator" unless it picks up from the current position of the internal iterator, rather than from the start of the hash. @foo= %bar always gives you the full contents of %bar, but while (my @x= each %bar) { push @foo, @x; } could omit elements if a previous 'each' iteration left off in the middle.
| [reply] [d/l] [select] |