2011-08-16 13 views
5

Wygląda na to, że Perl może mieć tylko łańcuchy znaków jako klucze mieszania. (Czy zostało to zmienione w pewnej wersji Perla?) Ograniczenie do używania ciągów jako klucza jest bardzo ograniczone. Co jeśli chciałbym, aby klucz lub obiekt był obiektem? W Pythonie łatwo jest użyć tablicy, krotki i innych obiektów, które można porównać jako klucze dyktujące. Perl ma możliwość porównywania elementów takich jak tablice dla równości, więc nie rozumiem, dlaczego nie mogą być używane jako klucze odwzorowujące.Czy Perl ma asocjacyjny typ tablicy, który może mieć dowolny typ kluczy?

Czy nie istnieje sposób użycia dowolnego typu klucza w Perlu? Czy istnieje moduł, który to zapewnia?

Odpowiedz

3

AFAIK Perl po prostu porządkuje klucze?

package Foo; 

use Moose; 
use overload ('""' => \&stringify); 

sub stringify { 
    return "xxx"; 
} 

package main; 

use v5.10; 
use Data::Dump 'pp'; 

my $foo = Foo->new; 
my $hash = {$foo => 'bar'}; 
say pp($hash); // { xxx => "bar" } 

W ten sposób można również użyć dowolnego klawisza skrótu. Zobacz także ten thread on Perl Monks.

Jeśli chodzi o równość, spójrz na equality operators in perlop. Operator == porównuje numerycznie, operator eq porównuje łańcuchowo. Oznacza to, że na przykład (4, 2) == (1, 2) jest prawdziwe (jako scalar (4, 2) jest 2), co może być dla ciebie zaskoczeniem.

3

Wbrew temu, co powiedziałeś, Perl NIE ma możliwości porównywania elementów takich jak tablice do równości, jak twierdzisz. Na początek Perl nie ma definicji równości macierzy. A jeśli definicja wymaga porównania zawartości tablicy, to Perl nie ma definicji równości dla większości rzeczy, które można znaleźć w tablicy.

Najbliższy Perl ma dla definicji tablice równości jest ich adres. Jeśli to, co chcesz używać, to jest całkiem proste:

$key = ['a', 'b']; 
$hash{$key} = [ $key, $val ]; # Prevents the key from being freed. 
print $hash{$key}[1]; 

W przeciwnym razie, Perl pozostawia ją do siebie do realizacji tego, co chcesz, a nie zmusza do korzystania z tego, co zapewnia. Widzę dwa główne podejścia.

Związany skrót, w zasadzie kod, który przedstawia interfejs skrótu, nie będąc faktycznie tablicą skrótów, może obsługiwać dowolny typ klucza. Możesz go użyć do zdefiniowania swojej wersji równości macierzy. Może istnieć nawet istniejący moduł (chociaż nie widziałem go po bardzo szybkim wyszukiwaniu).

Innym podejściem byłoby utworzenie funkcji, która tworzy unikalny klucz z wyrażenia klucza.

sub key{ "@_" } # Overly simplistic? 
$hash{key('a', 'b')} = $val; 
print $hash{key('a', 'b')}; 
+0

Perl również można porównać zawartość tablic: print „ok” if ([ „a”, 1 ] ~~ ['a', 1]); –

3

Tak, istnieje moduł do tego na CPAN: Tie::Hash::StructKeyed. Bierze pod uwagę całą strukturę, ale jako migawkę. każdy/keys zwróci oryginalne odniesienie.

1

Tak, używa fieldhash (Hash::Util::FieldHash dla 5.10+ i Hash::Util::FieldHash::Compat dla przed 5.10), aby zarejestrować twoje hashe jako fieldhashes, i możesz użyć dowolnego odwołania (a więc dowolnego obiektu) jako klucza dla tych skrótów (to odwołanie w istocie, i zapewnia logikę do czynienia z CLONEing drugiej nici i śmieci zbierając klucze), na przykład:

use Hash::Util qw/fieldhashes/; 
fieldhashes \my (%foo, %bar, %baz); 

my %data = (a => 1, b => 2, c => 3); 
my $stuff = {t => 2, u => 3, l => 9}; 
$foo{\%data} = 'x'; 
$foo{$stuff} = 'a'; 
$bar{\%data} = 'y'; 
$bar{$stuff} = 'b'; 
$baz{\%data} = 'z'; 
$baz{$stuff} = 'c'; 


print "$foo{\%data} $bar{\%data} $baz{\%data}\n"; 
print "$foo{$stuff} $bar{$stuff} $baz{$stuff}\n"; 
Powiązane problemy