Непосредственное изменение аргумента для подпрограммы - PullRequest
2 голосов
/ 20 июня 2011

Было бы намного проще в моем сценарии, если бы я мог использовать подпрограммы так, как работают shift, push и другие встроенные подпрограммы: все они могут напрямую изменять переданную ему переменную без необходимостивернуть изменения.

Когда я пытаюсь это сделать, переменная в какой-то момент копируется, и я, похоже, просто меняю копию.Я понимаю, что это было бы хорошо с ссылками, но это даже происходит с массивами и хешами, когда я чувствую, что просто передаю переменную, над которой я работал, в сабвуфер, чтобы можно было выполнить больше работы:*

Есть ли способ сделать это?Я понимаю, что это не лучшая практика, но в моем случае это было бы очень удобно.

Ответы [ 3 ]

10 голосов
/ 20 июня 2011

Вот для чего нужны прототипы:

#!/usr/bin/perl

use strict;
use warnings;

sub changeThis(\@);     # the argument will be seen as an array ref (prototype must come before the call!)

my @it = (10,11);  
changeThis @it;         # even when called with an array
print join(" ", @it),"\n"; #prints 10 11 12

sub changeThis(\@)
  { my( $ar)= @_; $ar->[2]= 12; }

См. http://perldoc.perl.org/perlsub.html#Prototypes для получения дополнительной информации.

Хотя на самом деле это не очень популярный метод, передача реальных ссылок на массивы, вероятно, является лучшей альтернативой с меньшим количеством волшебства.

5 голосов
/ 20 июня 2011

Проблема заключается в том, что дополнительный вызов расширяет переменную до списка значений, которые передаются в подпрограмму.Т.е. передается копия, а не сама переменная.Ваш дополнительный вызов равен:

changeThis(11, 12);

Если вы хотите изменить исходный массив, вместо него передайте ссылку:

use strict;
use warnings;

my @it = (10,11);
changeThis(\@it);
print join(" ", @it),"\n";

sub changeThis{
    my $array = shift;
    $$array[2] = 12;
}

Кроме того, @_[2] выдаст вам предупреждение:

Scalar value @_[2] better written as $_[2]

Если вы use warnings, что, конечно, следует.Нет веских оснований не включать предупреждения и строгие правила, если вы точно не знаете, что делаете.

2 голосов
/ 20 июня 2011

Как показывают предыдущие ответы, вы должны использовать ссылку, переданную подпрограмме.Кроме того, вы также можете использовать неявные ссылки, если вы хотите прочитать документацию для прототипов

sub changeThis(\@);

@it = (10,11);
changeThis @it;
print join(" ", @it),"\n"; #prints 10 11 12

sub changeThis(\@){
    $_[0][2] = 12;
}

(обратите внимание, что вы должны либо предварительно объявить ваши сабвуферы перед первым вызовом, либо поставить саб.определения сверху.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...