Une affectation de liste dans le contexte scalaire retourne le nombre d'éléments à droite:
my $greeting = (($hello, $there, $world) = (7,8)); #2 my @greeting = (($hello, $there, $world) = (7,8)); my $greeting_length = @greeting; #3
3 Réponses :
Il est documenté pour compter les éléments à droite dans Perlop (le dernier phrase dans la section des opérateurs d'affectation):
De même, une affectation de liste dans la liste contextuelle produit la liste des LValues attribuée à et une affectation de liste dans le contexte scalaire renvoie le nombre d'éléments produits par l'expression sur le côté droit de l'affectation. P> BlockQuote>
La raison pour laquelle cela fonctionne comme si vous pouvez écrire des choses comme ceci: p>
xxx pré> s'il comptait le nombre d'éléments sur le côté gauche de la gauche de l'affectation, ce serait une boucle infinie. P>
Si vous y réfléchissez, le nombre d'éléments sur le côté gauche est le même que sur le côté droit ou c'est une constante (quand vous 'Re attribuer à une liste de scalaires). Dans le premier cas, cela ne fait aucune différence de côté que vous comptez, et dans le second cas, compter le côté droit est plus utile. P>
d'autre part, dans la liste contextuelle, l'opérateur d'affectation renvoie la gauche Liste des mains, parce que c'est plus utile. Si vous l'utilisez dans un contexte qui modifie les éléments de liste, vous souhaitez modifier les variables qui ont été attribuées à. P>
re: votre commentaire strong> dans votre exemple,
(7,8) code> est une liste de deux éléments, c'est pourquoi l'opérateur d'affectation renvoie 2. Lorsque vous attribuez une liste plus courte à une liste plus longue des scalaires, le côté droit n'est pas "rembourré" avec < Code> Undef code> avant que l'affectation ne se produise. Au lieu de cela, toutes les variables qui n'ont pas eu de valeur qui leur sont associées à partir de la liste de droite sont réinitialisées à leur valeur par défaut. Pour une variable scalaire, c'est
undef code>. Pour les tableaux, c'est un tableau vide. Pour les hachages, c'est un hachage vide. P> p>
Votre réponse a du sens, je comprends pourquoi cela fonctionne de cette façon, mais je suis plus intéressé par la façon dont cela fonctionne. Voir mon commentaire sur ikegamis Post.
@Brian, dans le contexte de la liste, vous obtenez la liste des mains de gauche, mais dans le contexte scalaire, vous obtenez le compte de la liste de droite. Dans les deux cas, c'est parce que c'est la chose la plus utile à revenir. Voir ma réponse mise à jour pour plus de détails.
@Brian, il existe de nombreuses fonctions et opérateurs à Perl que dans le contexte scalaire renvoie quelque chose d'autre que le nombre d'éléments de retour dans le contexte de la liste. Vous devez lire les documents pour savoir quelle fonction ou l'opérateur reviendra.
"Je comprends pourquoi cela fonctionne de cette façon, mais je suis plus intéressé par la façon dont cela fonctionne." - Ceci est une déclaration dénuée de sens. Cela fonctionne de cette façon parce que la spécification linguistique dit qu'elle le fait. Comment ça marche est via la mise en œuvre PERL.
Cela me semble bizarre que ce contexte effets de ce côté est évalué: blockquote>Ce n'est pas le cas. Les deux côtés (opérandes) de l'opérateur d'affectation de liste ont évalué et si la cession de liste est évaluée dans le contexte scalaire ou le contexte de la liste n'affecte pas l'évaluation des opérandes. P>
si une affectation de liste est évaluée dans le contexte scalaire ou le contexte de la liste n'affecte que la valeur qu'elle revient. p>
J'ai déjà créé Opérateur d'affectation Liste Scalar VS , qui tente de préciser les différences entre les deux opérateurs d'affectation et Comment ils se comportent dans le contexte scalaire et de liste. P>
J'ai édité cette phrase pour clarifier un peu: Cela me semble bizarre que ce contexte affecte la partie de l'expression évaluée: Code> Je sais que ce contexte n'affecte pas l'évaluation et seul le résultat de retour, mais Je veux savoir comment ça marche. Si le côté droit d'une mission est évalué puis attribué au côté gauche, alors pourquoi le scalaire recevrait-il un 2? Le côté droit est évalué vers une liste de 3 éléments, qui devrait ensuite être attribuée au scalaire. C'est comme Perl décide juste d'ignorer les règles de priorité et de choisir la partie de l'expression devrait être renvoyée.
Sauf si, bien sûr, mon @greeting = (($ bello, $ là-bas, $ monde) = (7,8)) code> donnerait
@greeting code>
(7 , 8) code> au lieu de
($ bonjour, $ là-bas, $ monde) code>, maintenant cela ferait beaucoup plus de sens pour moi. Mais si
@greeting code> obtient
($ bonjour, $ là-bas, $ là-bas, $ monde) code> et
$ weaveting code> obtient le résultat de
(7,8 ) code> alors cela n'a pas de sens.
$ VOYAGE CODE> N'atre pas le résultat de
(7,8) code>. En fait, il est impossible pour
$ weaveting code> pour obtenir le résultat de ce
(7,8) code>, puisque ce
(7,8) code> évalue à Une valeur de liste et une valeur de liste ne peuvent pas être attribuées à un scalaire.both
@greeting code> et
$ VOYAGE code> Obtenez le résultat de la liste de liste, soit "Liste des valeurs" à laquelle son LHS a évalué "ou" nombre d'éléments auxquels son RHS a évalué "selon le contexte. Vous semblez impliquer qu'il serait préférable de retourner quelque chose de différent sans donner une raison quelconque quant à la façon dont d'autres résultats seraient utiles.
@ikegami, je pense qu'il disait qu'il serait plus cohérent si les expressions dans le contexte scalaire ont renvoyé le nombre d'éléments qu'ils reviendront dans le contexte de la liste. Et il a raison que ce serait plus cohérent. Il serait juste moins utile et Perl vise plus d'utilité que la cohérence.
@CJM, le choix des valeurs retournées est basé sur l'utilité. Il n'y a pas de cohérence. Chaque opérateur renvoie quelque chose de différent. Et c'est bien. Les opérateurs sont supposés faire des choses différentes. Avoir chaque opérateur se comporter comme s'il était entouré d'un (...) [0] code> ou
(...) [- 1] code> Lorsque cela s'appelle dans le contexte scalaire serait Dowright stupide, Pourtant, ce sont les seuls choix qui auraient un sens du tout pour tous les opérateurs.
@CJM, en ce qui concerne la cohérence, la liste de liste dans la liste contextuelle est 100% cohérente avec l'affectation scalaire dans le contexte de la liste. Les deux renvoient leur LHS comme des lvalues. Pour prétendre, il y a un manque de cohérence est complètement faux.
Si je fais: (((5 + 5) + (4 + 4)) code> Le résultat est de 18. Dans Perl, je pensais que ce contexte scalaire et de liste affecte cette valeur, 18. Si vous jetez un coup d'oeil À l'exemple précédent:
(($ bello, $ là-bas, $ monde) = (7,8)) code> n'est pas le résultat de l'expression elle-même
($ bonjour, $ là-bas, $ Monde) code>? Donc, le contexte scalaire et de liste affecterait cette valeur. Si l'expression fonctionne comme si elle, il semble que
(((5 + 5) + (4 + 4)) code> devrait donner 8, pas 18, ce qui n'aurait pas de sens. Cependant, maintenant, Darch qui a commenté My Post mentionné que les listes renvoient
Undef code> dans scalaire (pas le nombre d'éléments, comme une matrice.).
Donc, je vais simplement accepter que les expressions renvoient des résultats différents dans le contexte scalaire et de liste, au lieu de vous enliser avec les détails. Notez également que je ne discutais pas que cela aurait dû être fait comme je l'ai mentionné, je suis d'accord que la façon dont Perl gère cela est utile, j'essayais simplement de comprendre comment cela fonctionne, pas pourquoi cela fonctionne de cette façon.
@Brian, exemple parfait. Pensez-vous $ x = (((5 + 6) * (7 + 8)) code> met
11 code> ou
15 code> dans
$ x code>? Alors pourquoi pensez-vous
$ x = (($ bello, $ là-bas, $ monde) = (7,8)) code> doit mettre
($ bonjour, $ là-bas, $ monde) Code> ou
(7,8) code> dans
$ x code>? (Notez qu'il n'est pas possible de faire non plus!)
@Brian, les listes ne renvoient pas non plus dans le contexte scalaire, ils renvoient leur dernier élément évalué dans le contexte scalaire. par exemple. $ x = (4,5,6); code> met 6 dans
$ x code>. Darch a déclaré que cette liste particulière reviendrait négativement dans le contexte scalaire, mais cela n'a rien à voir avec votre question.
@Brian, exemple d'expressions renvoyant différents résultats dans le contexte scalaire et de liste: dire (scalaire (@a)); dire (@a); code> (nombre d'éléments dans
@a code> vs le nombre d'éléments dans
@a code>),
dire (scalaire (4, 5,6)); dire (4,5,6); code> (dernier élément de la liste évaluée dans le contexte sclar vs tous les éléments de la liste évalués dans le contexte de la liste), etc.
"N'est-ce pas le résultat de l'expression elle-même ($ bonjour, $ là-bas, $ monde)?" - Non, pas dans le contexte scalaire; Comme Ikégami a souligné, c'est impossible car une liste n'est pas un scalaire. Vous supposez que le contexte scalaire est une question de production d'une liste, puis de la convertir en scalaire, mais Perl n'est pas conçu de cette manière - le contexte scalaire produit une valeur utile. "J'essayais simplement de comprendre comment ça marche, pas pourquoi ça marche de cette façon." - Ceci est une distinction incohérente. Cela fonctionne de cette façon parce qu'il est défini pour fonctionner de cette façon. Il n'y a pas de "comment", autre que de regarder le code Perl.
Pourquoi évalue-t-il le côté droit et la production 2, au lieu de la liste nouvellement définie étant évaluée et renvoyée 3? P> blockQuote>
Parce que c'est ce que la définition de la langue dit qu'il devrait faire, car c'est ce que Larry Wall a décidé qu'il devrait faire. P>
Pour moi, il semble que $ bonjour obtient 7, $ il y a 8, et $ monde obtient Undef, alors cette liste est évaluée dans le contexte scalaire p> blockQuote>
Non, Perl ne fonctionne pas de cette façon. Vous supposez que le contexte scalaire n'est qu'une conversion du résultat qui aurait été obtenu dans le contexte de la liste à un scalaire en comptant le nombre d'éléments du résultat de la liste, mais ce n'est tout simplement pas correct ... contexte scalaire signifie qu'une opération (Dans ce cas, l'affectation) devrait produire un résultat scalaire, et il existe souvent des résultats scalaires plus utiles que le nombre d'éléments du résultat du contexte de liste, ce qui varie d'opérateur à l'opérateur ... Vous devez vérifier la documentation. pour quel scalaire produit; Ce n'est pas uniforme. Pour la tâche de la liste, la valeur scalaire est le nombre d'éléments du côté droit, car c'est beaucoup plus utile que le nombre de récepteurs, qui est constant. par exemple,
si (($ a, $ b) = s = ~ / $ re /) code> est vrai si le match produit des résultats, par opposition à toujours être vrai car il y a deux récepteurs. p>
Cela me semble étrange que ce contexte affecte la partie de l'évaluation L'expression est retournée p> blockQuote>
Il y a des choses très étranges à Perl. Ce sentiment d'étrangeté provient d'une inadéquation entre les modèles ... Dans ce cas, votre attente d'orthogonalité et de votre conviction que "Contexte scalaire" est un opérateur sur les listes, contre la conception pragmatique de Perl et la réalité que "contexte scalaire" Établit un contexte EM> qui détermine le résultat de produire. Notez que vous pouvez écrire vos propres fonctions qui produisent des résultats complètement différents em> en fonction du contexte de l'appel. P>
En effet, non: si la liste de gauche était la chose évaluée dans le contexte scalaire, la valeur serait
Undef code>. Une liste n'est pas un tableau.
@ Darque, cela n'a aucun sens.
($ bonjour, $ là-bas, $ monde) code> (et
(7,8) code>) ne peut pas être exécuté dans le contexte scalaire dans
($ bonjour, $ là-bas, $ monde) = (7,8) code>. L'affectation de liste pourrait revenir 3 si elle voulait, mais il n'y a aucune raison de.
Je répondais précisément à la phrase "alors [la liste ($ bonjour, $ là-bas, $ monde)] est évalué dans le contexte scalaire". Évaluer
mon ($ h, $ t, $ w $ w) = (7, 8, UNDF); scalaire ($ h, $ t, $ w) code> et voir que les listes ne sont pas des tableaux.
@darcy
scalaire ($ h, $ t, $ w, $ w) code> est identique à celui
scalaire ($ w) code> ... c'est un opérateur de séquence, pas une liste. RTFM: perdoc.perl.org/functions/scalar.html