It seems that a a sub
cannot access dynamic variables when it is used inside a map and that map is "return"ed.
Consider this piece of code:
sub start {
my $*something = 'foobar';
# WORKS
say 'first say-something:';
say-something;
# WORKS
say 'mapped say-something, no return:';
my @foo = (^2).map({say-something});
# ERROR: Dynamic variable $*something not found
say 'mapped say-something, with return:';
return (^2).map({say-something});
}
sub say-something {
say $*something;
1
}
start;
This will output:
first say-something:
foobar
mapped say-something, no return:
foobar
foobar
mapped say-something, with return:
Dynamic variable $*something not found
in sub say-something at main.raku line 18
in block <unit> at main.raku line 14
Why can't the sub access the dynamic variable? Is there a workaround for this?
Routine map
is lazy, so the block is not run until after start has returned.
From the documentation:
multi method map(Hash:D \hash) multi method map(Iterable:D \iterable) multi method map(|c) multi method map(\SELF: █; :$label, :$item) multi sub map(&code, +values)
Examples applied to lists are included here for the purpose of illustration.
For a list, it invokes &code for each element and gathers the return values in a sequence and returns it. This happens lazily, i.e. &code is only invoked when the return values are accessed.
So in your case, the map is evaluated once start returns, thus the dynamic variable is already out of scope.
A workaround for this is to force the map
to happen eagerly by adding .eager
return (^2).map({say-something}).eager
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With