Pourquoi devrais-je retourner une table de hachage ou d'un hachage de référence en Perl?
Quel est le moyen le plus efficace d'atteindre le ci-dessous? (Je sais qu'ils accomplissent la même chose, mais comment la plupart des gens ne présente entre les trois, et pourquoi?)
Fichier un.pl
my %hash = build_hash();
# Do stuff with hash using $hash{$key}
sub build_hash
{
# Build some hash
my %hash = ();
my @k = qw(hi bi no th xc ul 8e r);
for ( @k )
{
$hash{$k} = 1;
}
# Does this return a copy of the hash??
return %hash;
}
Fichier b.pl
my $hashref = build_hash();
# Do stuff with hash using $hashref->{$key}
sub build_hash
{
# Build some hash
my %hash = ();
my @k = qw(hi bi no th xc ul 8e r);
for ( @k )
{
$hash{$k} = 1;
}
# Just return a reference (smaller than making a copy?)
return \%hash;
}
Fichier c.pl
my %hash = %{build_hash()};
# Do stuff with hash using $hash{$key}
# It is better, because now we don't have to dereference our hashref each time using ->?
sub build_hash
{
# Build some hash
my %hash = ();
my @k = qw(hi bi no th xc ul 8e r);
for ( @k )
{
$hash{$k} = 1;
}
return \%hash;
}
Voir DONC, la question perl retour à partir de hachages fonctions, les meilleures pratiques (il apparaît dans la liste à droite de cette page...).
ne vous inquiétez pas sur les scalaires contexte de retour d'une fonction qui n'a pas de sens d'appeler dans un contexte scalaire
Nous couvrons une grande partie de ce Intermédiaires Perl (oreilly.com/catalog/9780596102067).
ne vous inquiétez pas sur les scalaires contexte de retour d'une fonction qui n'a pas de sens d'appeler dans un contexte scalaire
Nous couvrons une grande partie de ce Intermédiaires Perl (oreilly.com/catalog/9780596102067).
OriginalL'auteur user105033 | 2010-01-05
Vous devez vous connecter pour publier un commentaire.
Je préfère retourner un hachage de ref pour deux raisons. Un, il utilise un peu moins de mémoire car il n'y a pas de copie. De deux, il vous permet de faire cela si vous avez juste besoin d'un morceau de la table de hachage.
Apprendre à aimer de hachage références, vous allez voir que beaucoup une fois que vous commencez à l'aide d'objets.
OriginalL'auteur Schwern
Pourquoi ne pas retourner à la fois? Le contexte est une fonctionnalité très puissante en Perl pour permettre à vos fonctions de "faire ce que tu veux dire". Souvent, la décision de ce qui est une meilleure valeur de retour dépend de la façon dont le code appelant les plans de l'utilisation de la valeur, ce qui est exactement pourquoi Perl a la builtin
wantarray
.my($href) = build_hash(); # whoops
Un peu trop de l'aide pour ne pas gagner assez.Si quelqu'un qui travaille dans Perl ne peut reconnaître que la lvalue est imposant un contexte de liste sur la cession, ils ne vont pas aller très loin. Plutôt que de cacher ces caractéristiques de personnes, ceux qui comprennent entre eux devraient aider les autres à les utiliser correctement.
Ce n'est pas de ne pas comprendre les contextes. Son si vous vous attendez à build_hash() pour revenir à quelque chose de différent dans un contexte de liste. Ne faites pas confiance à l'utilisateur d'études et de toujours se souvient de la documentation de chaque fonction. Ses composés dans
my($foo)
etmy $foo
sont assez faciles au hasard d'échange. Aussifunction( build_hash() )
. Oups. Bogues subtils facilement oubliée. Enfin, il faut relancer une table de hachage n'a pas l'utilité de retour d'une liste. Une table de hachage doit être coincé dans une variable pour être utile. Retour d'une liste peut être utilisée implicitement, LISP style. Donc je doute de la valeur.OriginalL'auteur Eric Strom
Je retourne la référence à enregistrer le temps de traitement de l'aplatissement de la table de hachage dans une liste de valeurs scalaires, la construction de la nouvelle table de hachage et (éventuellement) les déchets de la collecte locale de hachage dans la sous-routine.
OriginalL'auteur David Harris
Ce que vous cherchez est un de hachage tranche:
La
x
opérateur est décrit à perldoc perlop.Voir perldoc perldsc et perldoc perlreftut des tutoriels sur des structures de données et de références (les deux doivent-lit pour les débutants comme les experts). Hachage tranches eux-mêmes sont mentionnés dans perldoc perldata.
Au sujet de son retour d'un hachage à partir d'une fonction, normalement vous devez retourner le hachage de lui-même, pas une référence. Vous pouvez utiliser une référence si le hachage est énorme et à la mémoire ou le temps est une préoccupation, mais qui ne devrait pas être votre premier souci: le code de travail est.
Les valeurs de retour des fonctions sont toujours des listes (d'où le retour d'un scalaire est essentiellement une liste d'un élément). Les hachages sont des listes en Perl: Vous pouvez attribuer l'une à l'autre interchangably (en supposant que la liste a un même nombre d'éléments, et il n'y a pas de clé de collisions qui ferait en sorte que certaines valeurs perdues lors de la conversion):
donne:
PS. Je recommande fortement l'écriture de petits programmes exemples comme celui ci-dessus pour jouer avec des structures de données et de voir ce qui se passe. Vous pouvez apprendre beaucoup de l'expérimentation de la!
hashof
exportés par le ProjectNamespace::DataManip fonction et environ mis en œuvre commesub hashof { return map { $_ => 1 } @_;}
(avec quelques prototypes de sucre et autres). Notrehash_slice_of($hashref, @list)
d'autre part les retours chaque paire clé-valeur quiexists
dans $hashref où la clé est aussi dans @liste. Comme un hachage fonction de manipulation, ils retournent tous les hachages (même de la taille des listes), de sorte que les valeurs de retour sont plus faciles à travailler et passer les uns aux autres.OriginalL'auteur Ether
a.pl
etc.pl
besoin d'une copie de la table de hachage à prendre (et le hachage interne à la fonction est marqué comme libre de la mémoire).b.pl
, d'autre part, construit le hachage juste une fois et exige peu de mémoire supplémentaire pour renvoyer une référence sur lesquels vous pouvez agir. Ainsib.pl
est plus susceptible d'être la forme la plus efficace des trois, à la fois dans l'espace et dans le temps.OriginalL'auteur PP.
Je vais aller à contre courant et ce que tout le monde est en train de dire, et de dire que je préfère avoir mes données retourné comme une table de hachage (eh bien, comme une même taille de la liste qui est susceptible d'être interprétée comme une table de hachage). Je travaille dans un environnement où nous avons tendance à faire des choses comme l'extrait de code suivant, et il est beaucoup plus facile de combiner et de les trier et de tranche et dés lorsque vous n'avez pas de déréférencement de chaque autre ligne. (Il est également agréable de savoir que quelqu'un ne peut pas endommager votre hashref parce que vous avez passé toute chose de valeur. edit: sauf si vous avez des références à d'autres objets/hachages/tableaux dans la table de hachage, les valeurs, alors que vous êtes en difficulté de toute façon).
Cela se rapproche de quelque chose que mon code peut faire: la construction d'une configuration d'un objet en fonction de divers configuration de la stratégie objets (dont certains que l'objet sait à propos de soi, plus l'homme) et le filtre puis certains d'entre eux comme hors de propos.
(Oui, nous avons beau des outils comme
hashgrep
ethashmap
etlkeys
que faire des choses utiles pour les tables de hachage. $a et $b, se mettre à la clé et la valeur de chaque élément dans la liste, respectivement). (Oui, nous avons des gens qui peuvent le programme à ce niveau. La location est odieux, mais nous avons un produit de qualité.)Si vous n'avez pas l'intention de faire quelque chose comme cela ressemble à de la programmation fonctionnelle, ou si vous avez besoin de plus de performance (avez-vous profiler?) alors bien sûr, l'utilisation hashrefs.
+1, c'est certainement une façon valable de le regarder.
OriginalL'auteur fennec
Je vais être en désaccord avec de l'Éther ici. Il fut un temps où j'ai pris cette position, mais il a rapidement trouvé moi-même descendant dans un enfer d'avoir à se souvenir de qui
sub
s retourné hachages et qui a renvoyé le hashrefs, qui était plutôt un sérieux obstacle à juste d'entrer le code de travail. Il est important de normaliser sur toujours retour d'une table de hachage/tableau ou toujours retour d'un hashref/arrayref sauf si vous voulez être constamment trébucher sur vous-même.Pour qui pour normaliser, je vois plusieurs avantages à aller avec les références:
Lorsque vous revenez à une table de hachage ou d'un tableau, ce que vous êtes réellement de retour est une liste contenant une stagnation de la copie de l'original de hachage/matrice. Tout comme en passant dans la table de hachage/tableau de paramètres à une
sub
, cela a l'inconvénient que vous ne pouvez envoyer qu'une seule liste à la fois. Certes, vous n'avez pas souvent besoin de revenir plusieurs listes de valeurs, mais il ne se passe, alors pourquoi choisir de normaliser faire les choses d'une manière qui s'oppose à elle?L' (généralement négligeable) performance/mémoire les bienfaits de la reprise d'un scalaire unique plutôt que d'un potentiel bien plus grand bloc de données.
Il permet de maintenir la cohérence avec OO code, qui souvent passe les objets (c'est à dire, le bienheureux références) d'avant en arrière.
Si, pour quelque raison que ce soit, il est important que vous avez une nouvelle copie de la table de hachage/tableau plutôt qu'une référence à l'original, le code appelant peut facilement en faire une, comme l'OP démontré dans
c.pl
. Si vous retournez une copie de la table de hachage, cependant, il n'y a aucun moyen pour l'appelant de tourner que dans une référence à l'original. (Dans les cas où cela est avantageux, la fonction peut en faire une copie et de renvoyer une référence à la copie, ainsi que de protéger l'original tout en évitant le "ce retourne hachages, que retourne hashrefs" l'enfer je l'ai mentionné plus tôt.)Comme Schwern mentionné, il est agréable d'être en mesure de faire
my $foo = $obj->some_data->{key}
.Le seul avantage que je vois à toujours retour hachages/tableaux, c'est qu'il est plus facile pour ceux qui ne comprennent pas les références ou ne sont pas à l'aise de travailler avec eux. Étant donné que le confort avec des références est plus qu'une question de semaines ou des mois pour se développer, suivie par des années ou des décennies de travail avec eux couramment, je ne considère pas cela un avantage significatif.
OriginalL'auteur Dave Sherohman
Prendre soin:
a.pl
renvoie une liste avec un même nombre d'éléments, pas une table de hachage. Lorsque vous affectez ensuite cette liste à un hachage de la variable, la valeur de hachage sera construit avec les éléments à la même indices que les clés et les éléments à l'étrange indices des valeurs. [EDIT: C'est la façon dont j'ai toujours vu la question, maissub { ... %hash }
effectivement se comporte un peu différemmentsub { ... @list }
. ]Pour la même raison, la construction d'une table de hachage, la façon dont vous décrivez, est aussi simple que:
Ma règle personnelle de base est d'éviter de faire référence, à moins que j'ai vraiment besoin d'eux (par exemple, structures imbriquées, ou lorsque vous avez vraiment besoin de passer une référence à la même chose).
EDIT: (je ne peux pas cliquer sur "ajouter un commentaire" lien plus?! Utilisez les touches souris ici...)
J'ai réfléchi un peu et je pense que de passage autour de hachage refs est probablement mieux après tout, en raison de la façon dont nous utilisons une table de hachage. Le paragraphe ci-dessus tient toujours pour tableau réf.
Merci pour vos commentaires Schwern et de l'Éther.
OriginalL'auteur Inshallah