Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl, is there any scenario in which ${foo[bar]} could be syntactically valid code?

Tags:

arrays

regex

perl

I am reading through O'Reilly's Programming Perl, 3rd Edition, and the text states that instead of using the ambiguous search pattern /$foo[bar]/, one should instead use /${foo[bar]}/ so that Perl doesn't mistake [bar] for a character class. Am I missing something, or are both of these statements syntactically incorrect due to the fact that they are trying to index into an array using a bareword string? I've checked the book's errata online and can't find any mention of this being a mistake in the book. Is there some scenario that I am overlooking in which that code could be valid?

like image 396
clarkb86 Avatar asked Dec 16 '22 02:12

clarkb86


1 Answers

I am reading through O'Reilly's Programming Perl, 3rd Edition, and the text states that instead of using the ambiguous search pattern /$foo[bar]/, one should instead use /${foo[bar]}/ so that Perl doesn't mistake [bar] for a character class. Am I missing something, or are both of these statements syntactically incorrect due to the fact that they are trying to index into an array using a bareword string?

Yes, you’re missing something: bar can be a function call:

$ perl -Mstrict -E 'sub bar() { 0 } say "foo" =~ /$ARGV[bar]/ || "FAIL"' foo
FAIL

$ perl -Mstrict -E 'sub bar() { 0 } say "foo" =~ /${ARGV[bar]}/ || "FAIL"' foo
1

$ perl -MO=Deparse -Mstrict -E 'sub bar() { 0 } say "foo" =~ /${ARGV[bar]}/ || "FAIL"' foo
sub bar () { 0 }
use strict 'refs';
BEGIN {
    $^H{'feature_unicode'} = q(1);
    $^H{'feature_say'} = q(1);
    $^H{'feature_state'} = q(1);
    $^H{'feature_switch'} = q(1);
}
say 'foo' =~ /$ARGV[0]/ || 'FAIL';
-e syntax OK

The exact quote, from page 73 of Programming Perl, 4th edition, is:

Within search patterns, which also undergo double-quotish interpolation, there is an unfortunate ambiguity: is /$foo[bar]/ to be interpreted as /${foo}[bar]/ (where [bar] is a character class for the regular expression), or as /${foo[bar]}/ (where [bar] is the subscript to array @foo)? If @foo doesn’t otherwise exist, it’s obviously a character class. If @foo exists, Perl takes a good guess about [bar] and is almost always right. If it does guess wrong, or if you’re just plain paranoid, you can force the correct interpretation with braces as shown earlier. Even if you’re merely prudent, it’s probably not a bad idea.

like image 183
tchrist Avatar answered Apr 08 '23 17:04

tchrist