Есть ли в Perl динамические переменные типа PHP?
В PHP я могу написать:
$vname = 'phone';
$$vname = '555-1234';
print $phone;
... И script выведет "555-1234".
Существует ли какой-либо эквивалент в Perl?
Есть ли способ ограничить $phone
областью локального блока, как если бы я написал my $phone
? Использование my $$vname
дает мне ошибку "Невозможно объявить скалярное разыменование в моем при...".
Ответы
Ответ 1
То, что вы пытаетесь сделать, называется "символической ссылкой". Хотя вы можете сделать это в Perl вам не следует. Символьные ссылки работают только с глобальными переменными - не лексическими (my
). Невозможно ограничить их сферу охвата. Символьные ссылки опасны. По этой причине они не работают под strict
прагмой.
В общем, всякий раз, когда вы думаете, что вам нужны символические ссылки, вы должны вместо этого использовать хэш:
my %hash;
$hash{phone} = '555-1234';
print $hash{phone};
Есть несколько случаев, когда symrefs полезны и даже необходимы. Например, механизм экспорта Perl использует их. Это расширенные темы. Когда вы будете готовы к ним, вам не нужно будет спрашивать, как это сделать.; -)
Ответ 2
Прочитайте Mark-Jason Dominus, чтобы не делать этого в Почему это глупо "использовать переменную как имя переменной" .
Вы ограничили объем ваших изменений на $phone, запустив блок с помощью
local $phone;
или даже
local $$vname;
(хотя либо изменяет $phone для любых подсистем, вызванных из вашего блока, поэтому он не совпадает с лексической областью объявления my()
.)
Ответ 3
Вы можете сделать это очень похоже:
$vname = "phone";
$$vname = "555-1234";
print $phone;
Но вы можете это не значит, что вам нужно. Лучший способ справиться с этим - как говорит Майкл Карман, ИСПОЛЬЗОВАТЬ HASH!
Ответ 4
Вы не можете сделать это при включенной строгой прагме, и обычно должна быть включена строгая прагма. Вы можете сделать это с помощью прагмы, хотя, взгляните на этот один лайнер:
perl -le 'my $vname = "phone"; ${ $vname } = "555-1234"; print $phone'
Это будет работать, но это не будет:
perl -Mstrict -le 'my $vname = "phone"; ${ $vname } = "555-1234"; print $phone'
"- Mstrict" говорит "использовать строгий".
Почти всегда лучше использовать хэш для чего-то подобного, что примерно такое же, как ассоциативный массив в PHP.
Ответ 5
Вы понимаете, что PHP наследует многие его функции от Perl, правильно?
Не только Perl может выполнять все символические ссылки, которые может использовать PHP,
use strict;
use warnings;
use 5.010;
our $test=1;
# Access $test through the special hash %::
say ${$::{test}}++;
# This is essentially what the previous line did.
say ${\$test}++
# Same as $test
say ${test}++;
{
# PHP simple symbolic ref
my $ref = "test";
no strict 'refs';
say $$ref++;
say ${"test"}++;
}
{
package d;
say ${$main::{test}}++;
my $ref = $main::{"test"};
say $$ref++;
$ref = \$main::test;
say $$ref++;
}