Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the conditions under which one can use a 'when' statement in Perl 5?

Documentation seems sparse regarding when statements outside of given blocks. It is said the when can be used when a 'topic' has been set, but when exactly is a topic considered set? Consider these cases:

for (@arr) {
  when { }
}

Seems this is the default, basic case, but I couldn't get even this working on my perl 5.14.2 - $ perl -Mfeature=switch -e 'foreach (qw(a b c)) { when (/a/) {print 'boom'} }' prints nothing. What am I doing wrong? Turned out this was just another bash quoting issue.

for my $elem (@arr) {
  when { }
}

Would this work? Will $elem automatically become the topic for when to use?

for (@arr) {
  $_ = some_expression($_);
  when { }
}

Would this work? Can the topic be set inside the loop?

Also, is there any difference when each of the above code segments uses foreach instead of for?

Basically, I'm very unclear on the topic of topics, so please enlighten me.

like image 841
Sundar R Avatar asked Jul 03 '13 20:07

Sundar R


2 Answers

It's a shell command construction error.

perl -Mfeature=switch -e 'foreach (qw(a b c)) { when (/a/) {print 'boom'} }'

should be

perl -Mfeature=switch -e 'foreach (qw(a b c)) { when (/a/) {print '\''boom'\''} }'

We can switch to double quotes to simplify

perl -Mfeature=switch -le'foreach (qw(a b c)) { when (/a/) {print "boom"} }'

And we can simplify further

perl -E'for (qw(a b c)) { when (/a/) { say "boom" } }'

Keywords for and foreach are one and the same to Perl.

Note that 5.18 marked given and when as experimental. It won't go away, but it will change. I explain what's going on here.


No, when doesn't use $elem; it always uses $_.


Yes, you can change $_ inside of for or given if you so desire. Note that foreach loops aliase their topic to the element being visited, so changing one changes the other.

my @x = qw( abc def );
for (@x) { $_ = uc($_); }
say @x;  # ABCDEF
like image 183
ikegami Avatar answered Nov 20 '22 20:11

ikegami


Ikegami spotted your actual problem. Regarding the other questions:

The two topicalizers are for/foreach and given. Other constructs that set $_ (the topic variable), are not considered topicalizers (e.g. map or grep).

If you run a foreach-loop with an explicit loop variable, the loop isn't considered to be a topicalizer. Therefore,

for my $x (1..3) {
  local $_ = $x;
  say when 2;
}

will work for the first iteration, but then die (Can't "when" outside a topicalizer) once the when is exited.

The given is different in that it doesn't localize $_, but gives a lexical $_. That is, given (@a) { foo; } is similar to { my $_ = \@a; foo; } (I think this might be fixed).

like image 21
amon Avatar answered Nov 20 '22 20:11

amon