9 votes

WhateverStar `&&` WhateverStar en Perl 6

* > 20 && * %% 5 utilisé dans grep semble incorrect, est-ce équivalent à une lambda WhateverCode qui prend 2 arguments? Comme expliqué sur SO

> my @a = 1,12,15,20,25,30,35,37;

> @a.grep: * > 20 && * %% 5 # Le résultat semble étrange, on s'attendait à (25 30 35)
(15 20 25 30 35)

> @a.grep: * %% 5 && * > 20
(25 30 35 37)

> @a.grep: { $_>20 && $_ %% 5 }
(25 30 35)

> @a.grep: all(* > 20, * %% 5)
(25 30 35)

> @a.grep: -> $a { all($a > 20, $a %% 5) }
(25 30 35)

> @a.grep: -> $a {$a > 20 && $a %% 5}
(25 30 35)

8voto

raiph Points 8552

Golfed

my &or  = * == 1 || * == 2 ;
my &and = * == 1 && * == 2 ;

say .signature, .(1), .(2)
  for &or, ∧

affiche :

(;; $whatevercode_arg_1 est brut)TrueFalse
(;; $whatevercode_arg_4 est brut)FalseTrue

Je ne sais toujours pas ce qui se passe, mais il est clair que la signature est pour un seul argument et le résultat est selon juste l'expression de droite pour le &and et celle de gauche pour le &or ce qui signifie que le code ne semble pas avoir, euh, laissé le résultat qui est, euh, juste. L'enquête se poursuit... (et non, je ne suis pas det remiker).

Mystère résolu

Il semblerait donc que les opérations logiques (&&, ||, et, ou, etc.) ne font pas de curry de Whatever. Ce qui est assez logique étant donné que "tous les opérateurs et les constructions syntaxiques ne font pas cuire * (ou Whatever-stars) vers WhateverCode". Logique, même, compte tenu de leur nature. Ils devraient probablement être ajoutés à la liste des exceptions sur cette page cependant.

Entre-temps, des opérateurs comme == font effectivement du curry de Whatever. Encore une fois, c'est suffisant étant donné que "les sous-expressions peuvent imposer leurs propres règles sur Whatever star".

Il est donc logique que &or et &and se transforment en...

Aha ! J'ai compris. Les * == 1 et * == 2 sont évalués au moment de la compilation et se transforment en WhateverCode. En tant que WhateverCode, ce sont juste des bouts de code. Ils sont définis. Ils sont True. (Cela ignore leur appel au moment de l'exécution.) Puis vient le && et est évalué avec le WhateverCode de la main droite. (Le || serait évalué avec son WhateverCode de la main gauche.)

D'où le comportement que nous observons.

Une solution

À la suggestion de @HåkonHægland, le code qui fonctionnerait donc est celui qui ne dépend pas du curry de Whatever des opérations logiques, c'est-à-dire :

my @a = 1,12,15,20,25,30,35,37;

say @a.grep: { $_ > 20 && $_ %% 5 } # (25 30 35)

Et maintenant ?

Maintenant, nous devons réfléchir aux modifications de documentation à proposer...

En fait, avant cela, confirmons que les opérations logiques ne sont pas censées faire du curry de Whatever...

Et pour commencer cela, je viens de passer en revue les résultats d'une recherche de TimToady commentaires sur #perl6 à propos de "currying" (il n'y en avait aucun sur #perl6-dev), à la recherche de ceux pertinents pour le cas que nous avons ici.

D'abord, celui de 2017 qui est incontestablement pertinent pour toute modification de documentation :

les documents de conception évitent en fait le mot "currying" ... mais il est difficile de faire en sorte que les gens utilisent les mots différemment de ce qu'ils font

Ensuite, celui de 2015 concernant && et || et autres :

|| et && et autres sont en réalité des opérateurs de flux de contrôle, rapidement convertis en 'if' et 'unless' ... ces opérations peuvent être curryfiées avec .assuming, je suppose

Et enfin, quelques-uns de 2010 qui semblent également importants (bien que certains ne soient peut-être plus applicables ?) :

tous les opérateurs curryfient un WhateverCode, que ce soit ou non un curryfication d'un Whatever

Je pense que nous pouvons conserver le mécanisme actuel comme solution de repli pour les opérateurs qui veulent toujours curryfier au moment de l'exécution

2voto

chenyf Points 1291
> my $d = * + * + * 
> $d.arity
3
> my $e = * == 1 || * == 2 || * == 3 
> $e.arity
1

comme le doc le dit :

Retourne le nombre minimum d'arguments positionnels qui doivent être passés pour appeler l'objet code.

je pense que toutes les trois étoiles dans * == 1 || * == 2 || * == 3 est la même chose.

> my $e = * == 1 && * == 2 && * > 3 
> $e(1)
False
> $e(2)
False
> $e(3)
False
> $e(4)
True

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X