Есть ли в Perl динамические переменные в стиле PHP?
В PHP я могу написать:
$vname = 'phone';
$$vname = '555-1234';
print $phone;
... И скрипт выдаст "555-1234".
Есть ли эквивалент в Perl?
Есть ли способ ограничить $phone
в объем локального блока, как если бы я написал my $phone
? С помощью my $$vname
выдает мне сообщение "Не могу объявить скалярное разыменование в моем at...".
5 ответов
То, что вы пытаетесь сделать, называется "символической ссылкой". Хотя вы можете делать это в Perl, вы не должны. Символьные ссылки работают только с глобальными переменными - не лексические (my
) те. Нет возможности ограничить их область применения. Символические ссылки опасны. По этой причине они не работают под strict
Прагма.
В общем, всякий раз, когда вы думаете, что вам нужны символические ссылки, вы должны использовать вместо этого хеш:
my %hash;
$hash{phone} = '555-1234';
print $hash{phone};
Есть несколько случаев, когда symrefs полезны и даже необходимы. Например, механизм экспорта Perl использует их. Это сложные темы. Когда вы будете готовы к ним, вам не нужно будет спрашивать, как это сделать.;-)
Прочитайте недовольство Марка-Джейсона Доминуса против того, чтобы делать это в разделе "Почему глупо использовать переменную как имя переменной".
Вы можете ограничить объем ваших изменений до $ phone, начав блок с
local $phone;
или даже
local $$vname;
(Хотя либо изменяет $ phone для любых подпрограмм, вызываемых из вашего блока, так что это не то же самое, что лексическая область действия my()
декларация).
Вы можете сделать это очень похожим способом:
$vname = "phone";
$$vname = "555-1234";
print $phone;
Но то, что ты можешь, не означает, что ты должен. Как сказал Майкл Карман, лучший способ справиться с этим - использовать хэш!
Вы не можете сделать это с включенной строгой прагмой, и строгая прагма обычно всегда должна быть включена. Вы можете сделать это с прагмой, хотя, посмотрите на этот лайнер:
perl -le 'my $vname = "phone"; ${ $vname } = "555-1234"; print $phone'
Это будет работать, но это не будет:
perl -Mstrict -le 'my $vname = "phone"; ${ $vname } = "555-1234"; print $phone'
"-Mstrict" говорит ему "использовать строгий".
Почти всегда лучше использовать хеш для чего-то подобного, что примерно равнозначно ассоциативному массиву в PHP.
Вы понимаете, что 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's 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++;
}