chriro2011
chriro2011

Reputation: 9

Why does "pos" disappear in Perl's string eval?

This short perl script

my $var='$array', $val;

$val='val'; eval("push(\@{$var},$val)"); print"@{$array}[0]\n";
$val='pos'; eval("push(\@{$var},$val)"); print"@{$array}[1]\n";
$val='fun'; eval("push(\@{$var},$val)"); print"@{$array}[2]\n";

results to

val

fun

Can anybody explain me, why val and fun got pushed on array, but pos does not?

I would expect that any value would be pushed by the eval-statement.

Upvotes: -2

Views: 104

Answers (2)

ikegami
ikegami

Reputation: 386541

First of all, ALWAYS use use strict; use warnings; or equivalent. It would have caught all of your errors.


These are the strings you are building and passing to eval:

push(@{array},val);
push(@{array},pos);
push(@{array},fun);

Without use strict;, these are equivalent to the following:

push( @array, "val" );
push( @array, pos() );
push( @array, "fun" );

@{array} is a weird and undocumented way of writing @array.

pos is a builtin function related to regex matching. In this program, it's returning undef. This gets stringified to the empty string (and warns) when printing.

val and fun are equivalent to "val" and "fun" because they couldn't possibly mean anything else. (They are "barewords".)


You want to evaluate the following code:

push( @array, $val )

To generate that string, you'd want

"push( \@$var, \$val )"   # Or: sprintf( 'push( @%s, $val )', $var )

So using eval EXPR, this would look like this:

eval( "push( \@$var, \$val )" )

You were missing the second \. (You also had extra curlies. These actually work, but it's an undocumented feature best avoided.)

This is fragile and dangerous, and using eval EXPR is completely unnecessary here. You could use the following:

{
   no strict qw( refs );
   push( @$var, $val );
}

But there's a reason we ask Perl to prevent us from doing this by adding use strict; to every program: It's a really really bad practice. You should use a hash instead.

my %arrays;
push @{ $arrays{ $var } }, $val;

Upvotes: 4

BarneySchmale
BarneySchmale

Reputation: 780

The second eval is evaluating the string 'push(@{$array},pos'. posis a builtin function that returns something related to regex matching. As no regex was used yet in the script, the function pos returns an undefined value. The undefined value is printed as an empty string.

The barewords "val" and "fun" are not builtin functions. Therefore they are conidered as plain strings.

Upvotes: 3

Related Questions