85 votes

Sténographie de fonction anonyme

Il y a quelque chose que je ne comprends pas sur les fonctions anonymes en utilisant le court notation #(..)

Les ouvrages suivants:

REPL>  ((fn [s] s) "Eh")
"Eh"

Mais ce n'est pas:

REPL>  (#(%) "Eh")

Ceci fonctionne:

REPL> (#(str %) "Eh")
"Eh"

Ce que je ne comprends pas, c'est pourquoi (#(%) "Hein") ne fonctionne pas et en même temps je n'ai pas besoin d'utiliser str en ((fn [s] s) "Hein")

Ils sont à la fois des fonctions anonymes et ils ont tous deux prendre, ici, un seul paramètre. Pourquoi la notation abrégée besoin d'une fonction, tandis que l'autre notation ne l'est pas?

126voto

Barmar Points 135986
#(...)

est une abréviation pour

(fn [arg1 arg2 ...] (...))

(où le nombre de argN dépend de combien de %N vous avez dans le corps). Donc, lorsque vous écrivez:

#(%)

il est traduit de:

(fn [arg1] (arg1))

Notez que ceci est différent de votre première fonction anonyme, qui est comme:

(fn [arg1] arg1)

Votre version retourne arg1, en tant que valeur, la version qui vient de l'expansion de l'abréviation essaie de l'appeler comme une fonction. Vous obtenez un message d'erreur parce qu'une chaîne n'est pas une fonction valide.

Depuis l'abréviation de fournitures d'un ensemble de parenthèses autour du corps, il ne peut être utilisé pour exécuter un seul appel de fonction ou forme spéciale.

65voto

DaoWen Points 14480

Les autres réponses ont déjà très bien souligné, l' #(%) vous avez posté effectivement s'étend à quelque chose comme (fn [arg1] (arg1)), ce qui n'est pas du tout le même que (fn [arg1] arg1).

@John Planéité remarquer que vous pouvez simplement utiliser identity, mais si vous êtes à la recherche d'une façon d'écrire identity à l'aide de l' #(...) expédition macro, vous pouvez le faire comme ceci:

#(-> %)

En combinant l' #(...) expédition macro avec l' -> threading macro il obtient étendu à quelque chose comme (fn [arg1] (-> arg1)), ce qui prend encore de l'expansion à l' (fn [arg1] arg1), ce qui est je veux juste que vous voulais. Je trouve aussi l' -> et #(...) macro combo utile pour l'écriture de simples fonctions qui renvoient des vecteurs, par exemple:

#(-> [%2 %1])

21voto

John Flatness Points 14473

Lorsque vous utilisez #(...), vous pouvez imaginer que vous êtes plutôt en train d'écrire (fn [args] (...)), y compris les parenthèses vous a commencé juste après le livre.

Donc, votre travail non-exemple convertit à:

((fn [s] (s)) "Eh")

ce qui évidemment ne fonctionne pas parce que l'on essaie d' appeler la chaîne "Eh". Votre exemple avec str fonctionne parce que maintenant, votre fonction est - (str s) au lieu de (s). (identity s) serait le plus proche de la télévision analogique à votre premier exemple, car il ne pas contraindre à la str.

C'est logique, si vous pensez à ce sujet, car d'autres que ce totalement exemple minimal, chaque fonction anonyme va demander quelque chose, de sorte qu'il serait un peu stupide d'exiger d'un autre ensemble imbriqué de parens pour réellement faire un appel.

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