2010-02-12 14 views
7

Mam klasy z metodą zwracającą mieszania. Normalnie, chciałbym uzyskać wynik tak:Jak usunąć dereferencję skrótu, który został zwrócony z metody klasy?

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

a następnie członków dostępu zwróconego hash tak:

$resp{key}{subkey}; 

w przypadku 2d hash.

I rysunek musi być jakiś sposób, aby połączyć to w jedną, eleganckiej linii, coś takiego:

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

To oczywiście nie jest dereferencjonowane właściwie jak Perl zwraca to podczas próby uruchomienia kodu:

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

próbując losowe sekwencje dereferencji, patrząc "References quick reference" on Perlmonks, ja przyszedłem z następujących, które Perl nie narzekać, ale również nie wraca co szukam:

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

Czy ktoś może mi powiedzieć, co to jest sekwencja ucieczki magicznej dereferencji?

+1

Każdy wydaje się chcieć sprawić, by życie jeszcze bardziej się zmieniło, zamieniając dwie idealnie dobre linie w jedną popsutą linię. Na pewno są lepsze rzeczy do przemyślenia. :) –

Odpowiedz

1

Wystarczy zwrócić hashref zamiast hash:

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

+0

Taki sam wynik jak przy -> przed {key}. Dzięki. – sgsax

+0

Ten sam wynik również, jeśli wyjmę -> łącznie. – sgsax

+0

Whazzup z -1? Drugie rozwiązanie zadziałało. – DVK

2

Chciałbym zwrócić odwołanie HASH z sub zamiast. W przeciwnym razie (prawdopodobnie) swój hash jest przekształcony następnie w listę hash znowu bez powodu:

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

Jest mniej kopiowanie zaangażowany po powrocie odniesienie tym samym bardziej efektywne.

+2

hash jest przekształcany na listę, a nie w tablicę. rozróżnienie jest subtelne, ale ważne. –

+0

Mogę wykonać tę pracę. Czy możesz wyjaśnić korzyści polegające na zwrocie hashref zamiast hasha? Mogę łatwo przerobić inne metody w klasie. Dzięki! – sgsax

+0

Dzięki Eric. Miałem zamiar napisać LISTĘ, ale minęło trochę czasu. Mój Perl jest teraz dość zardzewiały. – ziya

6

Zmiana sub wrócić odniesienie hash będzie działać najlepiej, ale aby uzyskać funkcjonalność szukasz:

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

który stworzy odniesienie skrótu z listy zwróconej przez sub, a następnie natychmiast dereference it

Edytuj: Zaletą zwracania hashrefa z twojego suba, zamiast skrótu (jako listy), jest w dużej mierze wydajność. W przypadku hashref skrót jest tworzony raz, a następnie uzyskiwany dostęp. W przypadku listy, skrót jest tworzony, następnie konwertowany na listę, a następnie tworzony ponownie, a następnie dereferencjonowany. W przypadku małych skrótów nie zajmie to zbyt wiele czasu, ale w przypadku większych jest to po prostu niepotrzebna praca dla środowiska wykonawczego. Zasadniczo, jeśli planujesz użyć danych jako listy w niektórych miejscach, a jako hash w innych, zwrócenie wartości mieszania jako listy jest w porządku. Ale jeśli zawsze planujesz użyć go jako hasha, zwrócenie referencji jest wyraźniejsze i szybsze.

+0

Dzięki temu uzyskałem dokładnie to, czego szukałem, zachowując mój istniejący kod klasy. Dzięki! – sgsax

9

To, co próbujesz zrobić, nie jest ani eleganckie, ani wskazane. W jakiś sposób udało się wywołać rutynę w kontekście skalarnym (to właśnie odpowiada "1/8").

Zwraca skrót nazwy.

Teraz przyjrzeć:

#!/usr/bin/perl 

package My::Mine; 

use strict; use warnings; 

sub test { 
    my %h = (
     a => { z => 1}, 
     b => { y => 2}, 
    ); 
    return %h; 
} 

package main; 

use strict; use warnings; 

my $class = 'My::Mine'; 

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

to nie zadziała. Zamiast tego, trzeba będzie zrobić:

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

Teraz to elegancki Zobacz perldoc -f print (Nie!).

Krótko mówiąc, zwróć odwołanie do skrótu.

Pamiętaj, że nowy anonimowy skrót, który budujesz, nie jest bezpłatny. Nie jest to również koszt zwrotu hasza jako listy płaskiej z podprogramu.

+0

Nie rozumiem, do czego służy tutaj +. Doceniam edukację. Dzięki. – sgsax

+3

+1 za wyjaśnienie w jasny sposób 1/8. Kolejną wadą jest to, że zwraca hasz - pogrążenie cię w fałszywym poczuciu bezpieczeństwa, jeśli uważasz, że "to kopia, więc mogę ją bezpiecznie zmodyfikować" - jednak wewnętrzne struktury danych są nadal refacjami, które nie są głęboko sklonowany, więc nie możesz ich bezpiecznie modyfikować. – DVK

+2

the + to podpowiedź do parsera, że ​​konstrukt {...} po wydruku nie jest obiektem pośrednim dla metody drukowania. jest to używane w sytuacjach takich jak 'print {sub_returns_a_file_handle()}" rzeczy do wydrukowania - zauważ, że przed otwartym cytatem nie ma przecinka ";" –

0

Jeśli zawsze potrzebujesz tylko jednego podklucza, napisz krótki podprogram, aby zrobić to za Ciebie i zapomnij o grze w golfa. Jedną z korzyści jest to, że możesz łatwo dodać pewne sprawdzanie poprawności:

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

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

     return $hashref->{$key}{$subkey}; 
     } 
Powiązane problemy