Je peux me tromper car personne ne l'a mentionné, mais j'avais également l'impression que la raison en est également l'héritage rubis de pouvoir appeler des fonctions sans crochets.
Arity est évidemment impliqué mais laisse le mettre de côté pendant un moment et utilise des fonctions sans arguments. Dans un langage comme javascript où les crochets sont obligatoires, il est facile de faire la différence entre passer une fonction en argument et appeler la fonction. Vous l'appelez uniquement lorsque vous utilisez les crochets.
my_function // argument
(function() {}) // argument
my_function() // function is called
(function() {})() // function is called
Comme vous pouvez le voir, le nommer ou non ne fait pas une grande différence. Mais l'élixir et le rubis vous permettent d'appeler des fonctions sans les crochets. C'est un choix de conception que j'aime personnellement, mais il a cet effet secondaire que vous ne pouvez pas utiliser uniquement le nom sans les crochets, car cela pourrait signifier que vous souhaitez appeler la fonction. C'est pour ça &
. Si vous laissez arity appart pendant une seconde, le fait d'ajouter le nom de votre fonction &
signifie que vous souhaitez explicitement utiliser cette fonction comme argument, et non ce qu'elle renvoie.
Maintenant, la fonction anonyme est un peu différente en ce qu'elle est principalement utilisée comme argument. Encore une fois, c'est un choix de conception, mais le raisonnement derrière cela est qu'il est principalement utilisé par les itérateurs du type de fonctions qui prennent des fonctions comme arguments. Vous n'avez donc évidemment pas besoin de les utiliser &
car ils sont déjà considérés comme des arguments par défaut. C'est leur but.
Maintenant, le dernier problème est que parfois vous devez les appeler dans votre code, car ils ne sont pas toujours utilisés avec une fonction de type itérateur, ou vous pouvez coder vous-même un itérateur. Pour la petite histoire, puisque ruby est orienté objet, la principale façon de le faire était d'utiliser la call
méthode sur l'objet. De cette façon, vous pouvez garder le comportement des crochets non obligatoires cohérent.
my_lambda.call
my_lambda.call()
my_lambda_with_arguments.call :h2g2, 42
my_lambda_with_arguments.call(:h2g2, 42)
Maintenant, quelqu'un a trouvé un raccourci qui ressemble à une méthode sans nom.
my_lambda.()
my_lambda_with_arguments.(:h2g2, 42)
Encore une fois, c'est un choix de conception. Maintenant, l'élixir n'est pas orienté objet et donc appelez à ne pas utiliser le premier formulaire à coup sûr. Je ne peux pas parler pour José mais il semble que la deuxième forme ait été utilisée dans l'élixir car elle ressemble toujours à un appel de fonction avec un caractère supplémentaire. C'est assez proche d'un appel de fonction.
Je n'ai pas pensé à tous les avantages et les inconvénients, mais il semble que dans les deux langues, vous pouvez vous en tirer avec les crochets tant que vous rendez les crochets obligatoires pour les fonctions anonymes. Il semble que ce soit:
Crochets obligatoires VS Notation légèrement différente
Dans les deux cas, vous faites une exception car vous faites en sorte que les deux se comportent différemment. Puisqu'il y a une différence, vous pourriez aussi bien la rendre évidente et opter pour la notation différente. Les parenthèses obligatoires sembleraient naturelles dans la plupart des cas, mais très déroutantes lorsque les choses ne se déroulent pas comme prévu.
Voici. Maintenant, ce n'est peut-être pas la meilleure explication au monde car j'ai simplifié la plupart des détails. De plus, la plupart sont des choix de conception et j'ai essayé de leur donner une raison sans les juger. J'aime l'élixir, j'aime le rubis, j'aime les appels de fonction sans crochets, mais comme vous, je trouve les conséquences assez erronées de temps en temps.
Et dans l'élixir, c'est juste ce point supplémentaire, alors qu'en rubis vous avez des blocs en plus. Les blocs sont incroyables et je suis surpris de voir tout ce que vous pouvez faire avec seulement des blocs, mais ils ne fonctionnent que lorsque vous avez besoin d'une seule fonction anonyme qui est le dernier argument. Ensuite, puisque vous devriez être capable de gérer d'autres scénarios, voici toute la confusion méthode / lambda / proc / block.
Quoi qu'il en soit ... cela est hors de portée.