Pourquoi avez-vous besoin de $ lorsque vous accédez à des éléments array et hash dans Perl?

StackOverflow https://stackoverflow.com/questions/153644

  •  03-07-2019
  •  | 
  •  

Question

Etant donné que les tableaux et les hachages ne peuvent contenir que des scalaires en Perl, pourquoi devez-vous utiliser le $ pour indiquer à l'interpréteur que la valeur est un scalaire lors de l'accès à des éléments de tableau ou de hachage? En d'autres termes, en supposant que vous ayez un tableau @myarray et un hachage %myhash, pourquoi devez-vous faire:

$x = $myarray[1];
$y = $myhash{'foo'};

au lieu de simplement faire:

$x = myarray[1];
$y = myhash{'foo'};

Pourquoi les éléments ci-dessus sont-ils ambigus?

Ne serait-ce pas du code Perl illégal s’il s’agissait de rien sauf un $ à cet endroit? Par exemple, les éléments suivants ne sont-ils pas illégaux en Perl?

@var[0];
@var{'key'};
%var[0];
%var{'key'};
Était-ce utile?

La solution

Les tranches ne sont pas illégales:

@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};

Et je suppose que cela fait partie de la raison pour laquelle vous devez spécifier si vous souhaitez obtenir une valeur unique du hachage / tableau ou non.

Autres conseils

Je viens d'utiliser

my $x = myarray[1];

dans un programme et, à ma grande surprise, voici ce qui m'est arrivé lorsque je l'ai exécuté:

$ perl foo.pl 
Flying Butt Monkeys!

C'est parce que tout le programme ressemble à ceci:

$ cat foo.pl 
#!/usr/bin/env perl

use strict;
use warnings;

sub myarray {
  print "Flying Butt Monkeys!\n";
}

my $x = myarray[1];

Ainsi, myarray appelle un sous-programme en lui passant une référence à un tableau anonyme contenant un seul élément, 1.

C'est une autre raison pour laquelle vous avez besoin du sceau sur un accès à un tableau.

Le sceau vous indique le type de retour du conteneur. Donc, si quelque chose commence par @, vous savez qu'il renvoie une liste. S'il commence par $, il retourne un scalaire.

Maintenant, s'il n'y a qu'un identifiant après le sigil (comme $foo ou @foo, il s'agit d'un simple accès variable. S'il est suivi d'un [, il s'agit d'un accès sur un tableau, s'il est suivi par un {, c’est un accès sur un hachage.

# variables
$foo
@foo

# accesses
$stuff{blubb} # accesses %stuff, returns a scalar
@stuff{@list} # accesses %stuff, returns an array
$stuff[blubb] # accesses @stuff, returns a scalar
              # (and calls the blubb() function)
@stuff[blubb] # accesses @stuff, returns an array

Certaines langues humaines ont des concepts très similaires.

Cependant, de nombreux programmeurs ont trouvé cela déroutant. Perl 6 utilise donc un sigil invariant.

En général, le compilateur Perl 5 veut savoir au moment de la compilation si quelque chose se trouve dans une liste ou dans un contexte scalaire. Ainsi, sans le signe de tête, certains termes deviendraient ambigus.

Ceci est valide Perl: @var[0]. C'est une tranche de tableau de longueur un. @var[0,1] serait une tranche de tableau de longueur deux.

@var['key'] n'est pas valide Perl car les tableaux ne peuvent être indexés que par des nombres, et les deux autres (%var[0] and %var['key']) ne sont pas valides en Perl car les tranches de hachage utilisent le {} pour indexer le hachage.

@var{'key'} et @var{0} sont tous deux des tranches de hachage valides. Évidemment, il n'est pas normal de prendre des tranches de longueur un, mais c'est certainement valable.

Voir la section slice de perldata perldoc pour plus d'informations sur le découpage en Perl.

Les gens ont déjà fait remarquer que vous pouvez avoir des tranches et des contextes, mais les sceaux sont là pour séparer les éléments qui sont des variables de tout le reste. Vous n'avez pas besoin de connaître tous les mots-clés ou noms de sous-programmes pour choisir un nom de variable sensible. C'est l'une des grandes choses qui me manque à propos de Perl dans d'autres langues.

Je peux penser à un moyen qui

$x = myarray[1];

est ambigu - et si vous vouliez un tableau appelé m?

$x = m[1];

Comment pouvez-vous distinguer cela d'un match de regex?

En d'autres termes, la syntaxe est là pour aider l'interpréteur Perl, eh bien, interpréter!

Dans Perl 5 (à modifier dans Perl 6), un sigil indique le contexte de votre expression.

  • Vous voulez un scalaire particulier dans un hachage, il s'agit donc de $hash{key}.
  • Vous voulez que la valeur d'un emplacement particulier sur un tableau, c'est donc $array[0].

Cependant, comme l'a souligné zigdon, les tranches sont légales. Ils interprètent ces expressions dans un contexte list .

  • Vous voulez une liste de 1 valeur dans un hachage @hash{key} fonctionne
  • Mais des listes plus volumineuses fonctionnent également, comme @hash{qw<key1 key2 ... key_n>}.

  • Vous voulez que quelques emplacements d'un tableau @array[0,3,5..7,$n..$n+5] fonctionne

  • @array[0] est une liste de taille 1.

Il n'y a pas de " contexte de hachage & ";,, donc ni %hash{@keys} ni %hash{key} n'ont de sens.

Vous avez donc "@" + "array[0]" < = > < sigil = contexte > + < expression d'indexation > comme l'expression complète.

Le sceau fournit le contexte de l'accès:

  • $ signifie un contexte scalaire (un scalaire variable ou un seul élément d'un hachage ou d'un tableau)
  • @ signifie le contexte de liste (un tableau entier ou une tranche de un hachage ou un tableau)
  • % est un hachage entier

En Perl 5, vous avez besoin des symboles ($ et @) car l'interprétation par défaut de l'identificateur sans mot est celle d'un appel à un sous-programme (vous évitant ainsi d'utiliser & et; dans la plupart des cas).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top