Используйте синтаксис *foo{THING}
, который описан в разделе Создание ссылок документации perlref.
Ссылка может быть создана с использованием специального синтаксиса, который с любовью называют синтаксисом *foo{THING}
. *foo{THING}
возвращает ссылку на слот THING в *foo
(это запись таблицы символов, которая содержит все, что известно как foo
).
$scalarref = *foo{SCALAR};
$arrayref = *ARGV{ARRAY};
$hashref = *ENV{HASH};
$coderef = *handler{CODE};
$ioref = *STDIN{IO};
$globref = *foo{GLOB};
$formatref = *foo{FORMAT};
Например:
#! /usr/bin/env perl
use strict;
use warnings;
our %hash = (Ralph => "Kramden", Ed => "Norton");
our @hash = qw/ apple orange banana cherry kiwi /;
my $ref;
$ref = *hash{HASH};
print $ref->{Ed}, "\n";
$ref = *hash{ARRAY};
print $ref->[1], "\n";
Выход:
Norton
orange
Что касается второй части вашего вопроса, добавьте
print $$ref{Ralph}, "\n";
после того, как Эд выдаст ожидаемый результат. Компилятор генерирует код для этой строки, который проходит в следующей последовательности:
- Извлечь запись пэда для
$ref
.
- Получите
$ref
штучку.
- Найдите ключ в хэше из шага 2.
Но не верьте мне на слово. Чтобы сократить объем производства, рассмотрим аналогичный двухслойный:
my $ref = { Ralph => "Kramden" };
print $$ref{Ralph};
Запуск его с помощью perl, скомпилированного для отладки, дает нам
$ debugperl -Dtls ref
[...]
(ref:1) nextstate
=>
(ref:2) pushmark
=> *
(ref:2) padsv($ref) # STEP 1
=> * \HV()
(ref:2) rv2hv # STEP 2
=> * HV()
(ref:2) const(PV("Ralph"\0)) # STEP 3a
=> * HV() PV("Ralph"\0)
(ref:2) helem # STEP 3b
=> * PV("Kramden"\0)
(ref:2) print
=> SV_YES
(ref:2) leave
[...]
Обратите внимание, что для глобалов это немного отличается.
Я не уверен, каково ваше большее намерение, но есть несколько важных предостережений. Обратите внимание, что typeglob представляет запись в таблице символов 1045 *, поэтому вы не можете получить лексические выражения таким образом, потому что они живут в пэдах, а не в таблице символов. Например, допустим, вы вставили my @hash = ("splat");
непосредственно перед присвоением $ref
в приведенном выше коде. Результат может вас удивить.
$ ./prog
"my" variable @hash masks earlier declaration in same scope at ./prog line 11.
Norton
orange
Поведение по отношению к скалярам также может быть удивительным.
*foo{THING}
возвращает undef
, если эта конкретная вещь еще не использовалась, за исключением скаляров. *foo{SCALAR}
возвращает ссылку на анонимный скаляр, если $foo
еще не использовался. Это может измениться в будущем выпуске.
Скажите нам, что вы пытаетесь сделать, и мы сможем дать вам конкретные, полезные предложения.