2010-02-12 9 views
7

Ich habe eine Klasse mit einer Methode, die einen Hash zurückgibt. Normalerweise würde ich das Ergebnis bekommen, wie so:Wie dereferenziere ich einen Hash, der von einer Methode einer Klasse zurückgegeben wurde?

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

Und dann Zugang Mitglieder des zurückgegebenen Hash wie folgt aus:

$resp{key}{subkey}; 

im Fall eines 2D-Hash.

ich es führen muss ein Weg sein, diese in eine einzige, elegante Linie zu kombinieren, etwa so:

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

Das ist offensichtlich nicht richtig wie Perl gibt diese dereferenziert, wenn Sie den Code auszuführen versuchen:

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

bei dem Versuch zufällig dereferencing Sequenzen, von "References quick reference" on Perlmonks suchen, kam ich mit dem Follow-up, die Perl beschwert sich nicht über, aber auch nicht zurück, was ich suche:

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

Kann mir jemand sagen, was die magische Dereferenzierung Escape-Sequenz ist, dies zu tun?

+1

Jeder scheint zu wollen, dass es härter lebt, indem er zwei vollkommen gute Linien in eine durcheinander geratene Linie verwandelt. Sicherlich gibt es bessere Dinge zum Nachdenken. :) –

Antwort

1

Rückkehr einfach eine hashref anstelle eines Hash:

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

+0

Gleiches Ergebnis wie bei -> vorher {Schlüssel}. Vielen Dank. – sgsax

+0

Gleiches Ergebnis auch wenn ich raus nehme -> insgesamt. – sgsax

+0

Whazzup mit -1? Zweite Lösung hat funktioniert. – DVK

2

Ich würde eine Hashreferenz von der Unter stattdessen zurück. Im anderen Fall (wahrscheinlich) Ihre Hash wird in eine Liste wendet sich dann in einen HASH wieder ohne Grund:

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

Es gibt weniger Kopieren beteiligt, wenn die Referenz Rückkehr daher effiziente.

+2

der Hash wird in eine Liste, kein Array umgewandelt. Die Unterscheidung ist subtil, aber wichtig. –

+0

Ich kann das machen. Können Sie den Vorteil der Rückgabe eines Hashrefs anstelle eines Hashs erklären? Ich kann die anderen Methoden in der Klasse einfach überarbeiten. Vielen Dank! – sgsax

+0

Danke Eric. Ich wollte LIST schreiben, aber es ist schon eine Weile her. Mein Perl ist jetzt ziemlich rostig. – ziya

6

die Unter Ändern eines Hashreferenz am besten funktionieren würde, zurückzukehren, aber die Funktionalität, die Sie suchen bekommen:

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

, die eine Hash-Referenz aus der Liste von sub zurück schaffen wird, und dann sofort dereferenzieren es

Edit: Der Vorteil, einen Hashref von Ihrem Sub anstelle von einem Hash (als eine Liste) zurückgibt, ist weitgehend eine der Leistung. Im Fall von hashref wird der Hash einmal erstellt und dann darauf zugegriffen. Im Listenfall wird der Hash erstellt, dann in eine Liste konvertiert, dann erneut erstellt und dann dereferenziert. Für kleine Hashes wird dies nicht zu viel Zeit in Anspruch nehmen, aber für größere Hashes ist es nur unnötige Arbeit für die Laufzeit. Wenn Sie die Daten an einigen Stellen als Liste und in anderen als Hash verwenden möchten, ist die Rückgabe des Hashs als Liste in Ordnung. Aber wenn Sie immer planen, es als Hash zu verwenden, wird die Referenz klarer und schneller zurückgegeben.

+0

Das bringt mir genau das, wonach ich gesucht habe, während ich meinen bestehenden Klassencode beibehalten habe. Vielen Dank! – sgsax

9

Was Sie versuchen, ist weder elegant noch ratsam. Sie haben es irgendwie geschafft, die Routine im skalaren Kontext aufzurufen (das entspricht der "1/8").

Geben Sie eine Referenz zurück.

Nun nehmen Sie einen Blick auf:

#!/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"; 

, die nicht funktionieren. Stattdessen werden Sie zu tun haben:

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

Nun, das ist elegant perldoc -f print anzeigen (Nicht!).

Lange Rede kurzer Sinn, einen Verweis auf den Hash zurückgeben.

Beachten Sie, dass der frische anonyme Hash, den Sie erstellen, nicht frei ist. Die Kosten für das Zurückgeben eines Hashwerts als eine flache Liste aus einer Subroutine sind auch nicht.

+0

Ich verstehe nicht, wofür das + hier verwendet wird. Ich schätze die Ausbildung. Vielen Dank. – sgsax

+3

+1 zur Erläuterung von 1/8 klar. Ein weiterer Nachteil ist das Zurückgeben eines Hashes - es bringt Sie in ein falsches Sicherheitsgefühl, wenn Sie denken "Dies ist eine Kopie, also kann ich sie sicher modifizieren" - doch die Interna der Datenstruktur sind immer noch Refs, die es nicht sind tief geklont, damit Sie sie nicht sicher modifizieren können. – DVK

+2

Das + ist ein Hinweis für den Parser, dass das Konstrukt {...} nach dem Ausdruck kein indirektes Objekt für die Druckmethode ist. Dies wird in Situationen wie "print {sub_returns_a_file_handle()}" zum Drucken verwendet - beachten Sie, dass vor dem offenen Zitat kein Komma steht ";" –

0

Wenn Sie immer nur einen Unterschlüssel erhalten möchten, schreiben Sie eine kurze Subroutine, um das für Sie zu tun und vergessen Sie, Ihre Linie zu spielen. Ein Vorteil ist, dass Sie leicht eine Überprüfung der Gesundheit hinzufügen können:

Verwandte Themen