Как разыменовать хеш, который был возвращен из метода класса? - PullRequest
7 голосов
/ 13 февраля 2010

У меня есть класс с методом, который возвращает хэш. Обычно я получаю результат примерно так:

%resp = $myclass->sub($foo);

А затем получить доступ к членам возвращенного хэша следующим образом:

$resp{key}{subkey};

в случае двумерного хэша.

Я полагаю, что должен быть способ объединить это в одну элегантную линию, что-то вроде этого:

$myclass->sub($foo)->{key}{subkey}

Это явно не разыменовывается должным образом, поскольку Perl возвращает это при попытке запустить код:

Can't use string ("1/8") as a HASH ref

При попытке случайного разыменования последовательностей, просматривая "Краткий справочник ссылок" на Perlmonks , я придумал следующее, на которое Perl не жалуется, но и не возвращает то, что я ищу :

$%{$myclass->sub($foo)}->{key}{subkey}

Может кто-нибудь сказать мне, что такое магическая разыменовывающая последовательность побега, чтобы сделать это?

Ответы [ 5 ]

9 голосов
/ 13 февраля 2010

То, что вы пытаетесь сделать, не изящно и не желательно. Вам каким-то образом удалось вызвать подпрограмму в скалярном контексте (именно этому соответствует "1/8").

Возвращает ссылку на хеш.

Теперь взгляните на:

* +1007 *

Это не сработает. Вместо этого вам нужно будет сделать:

print +{ $class->test }->{a}{z}, "\n";

Это элегантно ( Не! ) См. perldoc -f print .

Короче говоря, верните ссылку на хеш.

Обратите внимание, что созданный вами новый анонимный хэш не является бесплатным. Также не стоит возвращать хеш в виде плоского списка из подпрограммы.

6 голосов
/ 13 февраля 2010

Изменение сабвуфера для возврата ссылки на хеш будет работать лучше, но для получения требуемой функциональности:

{ $myclass->sub($foo) }->{key}{subkey}

, который создаст ссылку на хеш из списка, возвращенного sub, а затем немедленно разыменует его

Редактировать: Преимущество в возврате хеш-ссылки из вашего сабвуфера, а не хеш-функции (в виде списка) в значительной степени зависит от производительности. В случае хэш-ссылки, хэш создается один раз, а затем осуществляется доступ. В случае списка хеш создается, затем преобразуется в список, затем снова создается и затем разыменовывается. Для маленьких хэшей это не займет слишком много времени, но для больших хэшей это просто ненужная работа для среды выполнения. По сути, если вы планируете использовать данные в виде списка в некоторых местах и ​​в качестве хеша в других, то возвращать хеш в виде списка можно. Но если вы всегда планируете использовать его в качестве хэша, возврат ссылки будет более понятным и быстрым.

2 голосов
/ 13 февраля 2010

Я бы вместо этого вернул ссылку на HASH. В противном случае (вероятно) ваш хэш превращается в LIST, а затем снова в HASH без всякой причины:

sub mysub() {
  ...
  return \%myhash;
}

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

1 голос
/ 13 февраля 2010

Просто верните хэшреф вместо хеша:

$myclass->sub($foo)->{key}->{subkey}

0 голосов
/ 13 февраля 2010

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

 sub get_subkey {
      my( $class, $arg, $key, $subkey ) = @_;

      my $hashref = $class->method( $arg );
      return unless ref $hashref;

      return $hashref->{$key}{$subkey};
      }
...