2017-02-07 1 views
-1

Использование shift в пределах eval строки, которая находится внутри sub не работает: сдвиг не работает в пределах Eval строки

Пример 1 (с использованием eval):

grab_variable($variable1,$variable2,$variable3); 
print $variable1.$variable2.$variable3; #should print: 123 

sub grab_variable { 
    my $number_of_parameters = @_; 
    my $command1; 
    my $command2; 
    for (my $i = 1; $i <= $number_of_parameters; $i++) { 
     $command1.= "\$RefVariable".$i." = \\shift;\n"; 
      #Generates string like: 
       #$RefVariable1 = \shift; 
       #$RefVariable2 = \shift; 
       #... 
    } 
    eval $command1; 
    for (my $i = 1; $i <= $number_of_parameters; $i++) { 
     $command2.= "\$\{\$RefVariable".$i."\} = ".$i.";\n"; 
      #Generates string like: 
       #${$RefVariable1} = 1; 
       #${$RefVariable2} = 2; 
       #... 
    } 
    eval $command2; 
} 

Пример 2 (прямой код) :

grab_variable($variable1,$variable2,$variable3); 
print $variable1.$variable2.$variable3; #Prints: 123 

sub grab_variable { 
    $RefVariable1 = \shift; 
    $RefVariable2 = \shift; 
    $RefVariable3 = \shift; 
    ${$RefVariable1} = 1; 
    ${$RefVariable2} = 2; 
    ${$RefVariable3} = 3; 
} 

Пример 1 является динамическим и достигает решения моей реальной (не упрощенной) проблемы. Как я могу сделать \shift работу внутри строки кода eval?

В частности, я пытаюсь сделать функцию (подпрограмму), который принимает любое количество переменных (в качестве аргументов) и передавался в качестве ссылок (не значений), потому что она должна изменить их.

+2

'$ grab_variable ($ Var)' является недействительным синтаксис. – simbabque

+1

'' \ $ RefVariable ". $ i' является [запахом кода] (http://stackoverflow.com/questions/1549685/how-can-i-use-a-variable-as-a-variable-name-in-perl). Разве нет способа сделать это с помощью массивов? – mob

+0

Кроме того, если вы просто пытаетесь выполнить передачу по ссылке, содержимое '@ _' уже является псевдонимом аргументов, переданных подпрограмме. '$ Исх = \ сдвиг; $$ ref = "foo"; 'равнозначно' $ _ [0] = "foo" ' – mob

ответ

3

В подлодки, shift коротка для shift(@_).

Снаружи, shift не подходит для shift(@ARGV).

Это относится к коду, переданному также eval EXPR.

Заменить

$command1.= "\$RefVariable".$i." = \\shift;\n"; 

с

$command1.= "\$RefVariable".$i." = \\shift(\@_);\n"; 

Вы должны всегда использовать use strict; use warnings qw(all);. Ваш код делает все, что вам не нужно делать, и это поймает это.

Я не уверен, что вы пытаетесь достичь, но вы рассмотрели

sub set_variables { 
    for my $i (0..$#_) { 
     $_[$i] = $i;  # Changing the elements of @_ changes them in the caller. 
    } 
} 

set_variables(my ($var1, $var2, $var3)); 

say "$var1 $var2 $var3"; 

или

sub grab_variables { return \@_; } 

my $ref_variables = grab_variables(my ($var1, $var2, $var3)); 

for my $i (0..$#$ref_variables) { 
    $ref_variables->[$i] = $i; 
} 

say "$var1 $var2 $var3"; 
+0

Да, я слишком близко понимаю, почему 'shift' не работает в' eval EXPR'. Что означает 'shift' в рамках' eval EXPR'? Кажется, что это не означает 'shift (@_)' внутри eval. – Omar

+1

Ваш код не находится в sub, поэтому 'shift' является коротким для' shift (@ARGV) '. – ikegami

+0

Большое спасибо. Полностью объяснено, почему «shift» не работает. – Omar

2

Perl уже выполняет пропуски для подпрограмм, что даже проще, чем передача по ссылке. Содержание @_ - это псевдонимы входных данных подпрограммы; изменение $_[$i] изменяет i-ые значения, переданные под.

sub grab_variables { 
    for my $i (0 .. $#_) { 
     $_[$i] = $i+1; 
    } 
} 
my ($variable1,$variable2,$variable3); 
grab_variable($variable1,$variable2,$variable3); 
print $variable1.$variable2.$variable3;   #Prints: 123