Есть ли в Perl PHP-подобные динамические переменные? - PullRequest
11 голосов
/ 12 ноября 2008

В PHP я могу написать:

$vname = 'phone';
$$vname = '555-1234';
print $phone;

... И скрипт выдаст «555-1234».

Есть ли эквивалент в Perl?

Есть ли способ ограничить $phone областью действия локального блока, как если бы я написал my $phone? Использование my $$vname дает мне сообщение «Не могу объявить скалярное разыменование в моем at ...».

Ответы [ 5 ]

56 голосов
/ 12 ноября 2008

То, что вы пытаетесь сделать, называется «символической ссылкой». Хотя вы можете сделать это в Perl , вы не должны . Символьные ссылки работают только с глобальными переменными, а не с лексическими (my). Нет возможности ограничить их область применения. Символические ссылки опасны. По этой причине они не работают под strict прагмой.

В общем, когда вам кажется, что вам нужны символьные ссылки, вы должны использовать вместо этого хеш:

my %hash;
$hash{phone} = '555-1234';
print $hash{phone};

Есть несколько случаев, когда symrefs полезны и даже необходимы. Например, механизм экспорта Perl использует их. Это сложные темы. Когда вы будете готовы к ним, вам не нужно будет спрашивать, как это сделать. ; -)

13 голосов
/ 12 ноября 2008

Прочитать недовольство Марка-Джейсона Доминуса против этого в Почему глупо `использовать переменную в качестве имени переменной '.

Вы можете ограничить объем ваших изменений до $ phone, начав блок с

local $phone;

или даже

local $$vname;

(Хотя любой из них изменяет $ phone для любых подпрограмм, вызываемых из вашего блока, так что это не то же самое, что лексическая область объявления my().)

8 голосов
/ 12 ноября 2008

Вы можете сделать это очень похожим образом:

$vname = "phone";
$$vname = "555-1234";
print $phone;

Но то, что ты можешь, не значит, что ты должен. Лучший способ справиться с этим - , как говорит Майкл Карман , ИСПОЛЬЗОВАТЬ ХАШ!

6 голосов
/ 12 ноября 2008

Вы не можете сделать это с включенной строгой прагмой, и строгая прагма обычно всегда должна быть включена. Вы можете сделать это с прагмой, хотя, посмотрите на этот лайнер:

perl -le 'my $vname = "phone"; ${ $vname } = "555-1234"; print $phone'

Это будет работать, но это не будет:

perl -Mstrict -le 'my $vname = "phone"; ${ $vname } = "555-1234"; print $phone'

"- Mstrict" говорит ему "использовать строгий".

Почти всегда лучше использовать хеш для чего-то вроде этого, который примерно такой же, как ассоциативный массив в PHP.

0 голосов
/ 21 июля 2009

Вы понимаете, что 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++;
}
...