2009-01-30 5 views
1

Est-il possible de définir des sous-programmes anonymes dans un constructeur de hachage en Perl?Est-il possible de définir des sous-programmes anonymes dans un constructeur de hachage en Perl?

Je suis en train de faire quelque chose comme ceci:

my %array = { one => sub { print "first $_[0]" }, 
       two => sub { print "next $_[0]" }, 
       three => sub { print "last $_[0]" }}; 

$array{$foo}->('thing'); 

Mais il ne fonctionne pas. Le code semble s'exécuter et compiler, mais les valeurs dans le tableau sont vides. Si je fais ceci:

my %array; 

$array{'one'} = sub { print "first $_[0]" }; 
$array{'two'} = sub { print "next $_[0]" }; 
$array{'three'} = sub { print "last $_[0]" }; 

$array{$foo}->('thing'); 

Ensuite, il semble bien fonctionner. Donc, j'ai une solution de contournement, mais cela ne fait que m'embêter et je me demandais si quelqu'un sait si c'est possible et, si oui, quelle est la syntaxe.

+0

En Perl, ils sont appelés des hachages, et non des tableaux associatifs. – gpojd

+0

Désolé ... Je pense que l'édition du livre de chameaux que j'ai appris s'appelait les tableaux associatifs. Ma faute. –

Répondre

11

On dirait que vous affectez dans le hachage de manière incorrecte. L'utilisation de {} construit une référence de hachage anonyme, que vous affectez à un scalaire. Mais vous affectez à un hachage nommé (%array).

Vous devez attribuer dans un scalaire:

my $array = { one => sub { print "first $_[0]" }, 
       two => sub { print "next $_[0]" }, 
       three => sub { print "last $_[0]" }}; 

$array->{$foo}->('thing'); 

Ou de ne pas utiliser la syntaxe du constructeur anon:

my %array = (one => sub { print "first $_[0]" }, 
       two => sub { print "next $_[0]" }, 
       three => sub { print "last $_[0]" }); 

$array{$foo}->('thing'); 
+0

Considérez ce post résolu. =) –

+2

Bien sûr, ce serait encore plus correct, si nous avons appelé cette variable% hash au lieu de% array – innaM

+0

@Manni: Bon point. Alors que les hachages sont techniquement appelés aussi "tableaux associatifs", en pratique, tous les programmeurs Perl que je connais utilisent "array" pour désigner exclusivement les tableaux simples, et "hash" pour désigner les hachages. –

6

En effet, dans le premier cas, vous créez un hashref pas un hachage, ce que vous voulez est:

my $array; 
$array = { one => ... }; # not %array = { .. }; 
... 
$array->{one}->('thing'); 
+0

Ou juste changer les parenthèses en parens et% tableau peut rester un hachage, pas un ref. – kingkongrevenge

2

Il est censé être entre parenthèses, pas d'accolades:

my %array = (one => sub { print "first $_[0]" }, 
       two => sub { print "next $_[0]" }, 
       three => sub { print "last $_[0]" }}); 

'{a => 1, b => 2}' produit une référence à un hachage. Donc, ce qui suit travaillerait aussi:

my $array = { one => sub { print "first $_[0]" }, 
       two => sub { print "next $_[0]" }, 
       three => sub { print "last $_[0]" }}; 

$array->{one}->('thing'); 
3

J'ai passé quelque chose comme deux heures à essayer de retrouver ce exact braces-vs-parentheses problem dans un script pas trop longtemps. Si vous utilisez le commutateur -w sur Perl, vous obtiendrez un avertissement "Référence trouvée où une liste de taille paire est attendue", ce qui donne au moins une indication sur l'emplacement de recherche. Aujourd'hui, tous les scripts Perl devraient commencer par:

#!/usr/bin/perl -w 

use strict; 

Votre vie Perl sera infiniment moins frustrant.

+1

Je recommanderais d'utiliser des avertissements sur -w, car le premier peut être désactivé dans une portée lexicale si nécessaire. – friedo

4

Greg Hewgill est sur la bonne voie. Activez toujours le pragma strict. En outre, activez toujours les avertissements, mais je recommande de ne pas utiliser l'option -w dans votre code.

A la place, profitez du pragma use warnings. De cette façon, vous pouvez désactiver de manière sélective des groupes d'avertissements particuliers dans des zones de portée lexicale de votre code.

Par exemple:

use strict; 
use warnings; 

foo('bar'); 
foo(); 

sub foo { 
    no warnings 'uninitialized'; 

    my $foo = shift || 'DEFAULT'; 

    print "Foo is $foo\n"; 
} 

utilisation cohérente des pragmas strictes et avertissements vous épargnera des heures et des heures de temps.

Questions connexes