wake-up-neo.com

Kurzform der anonymen Funktion

Ich verstehe etwas nicht über anonyme Funktionen mit der Kurznotation # (..)

Die folgenden Arbeiten:

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

Das tut es aber nicht:

REPL>  (#(%) "Eh")

Das funktioniert:

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

Ich verstehe nicht, warum (# (%) "Eh") nicht funktioniert und gleichzeitig str nicht in - verwendet werden muss. ((fn [s] s) "Eh")

Sie sind beide anonyme Funktionen und nehmen hier beide einen Parameter an. Warum benötigt die Kurzschreibweise eine Funktion, die andere nicht?

84
Cedric Martin
#(...)

ist eine Abkürzung für

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

(wobei die Anzahl von argN davon abhängt, wie viele% N sich in Ihrem Körper befinden). Wenn Sie also schreiben:

#(%)

es wird übersetzt in:

(fn [arg1] (arg1))

Beachten Sie, dass sich dies von Ihrer ersten anonymen Funktion unterscheidet, die wie folgt lautet:

(fn [arg1] arg1)

Ihre Version gibt arg1 als Wert zurück. Die Version, die aus dem Erweitern der Kurzform stammt, versucht, sie als Funktion aufzurufen. Sie erhalten eine Fehlermeldung, weil eine Zeichenfolge keine gültige Funktion ist.

Da die Kurzform eine Reihe von Klammern um den Text herum enthält, kann sie nur zum Ausführen eines einzelnen Funktionsaufrufs oder eines speziellen Formulars verwendet werden.

123
Barmar

Wie die anderen Antworten bereits sehr deutlich gemacht haben, erweitert sich das #(%), das Sie gepostet haben, tatsächlich auf etwas wie (fn [arg1] (arg1)), Was überhaupt nicht mit (fn [arg1] arg1) Identisch ist.

@ John Flatness wies darauf hin, dass Sie nur identity verwenden können, aber wenn Sie nach einer Möglichkeit suchen, identity mit dem Dispatch-Makro #(...) zu schreiben, können Sie dies tun so was:

#(-> %)

Durch Kombinieren des Dispatch-Makros #(...) mit dem Threading-Makro -> wird es zu etwas wie (fn [arg1] (-> arg1)) Erweitert, das wieder zu (fn [arg1] arg1), das ist nur wollen, dass du wolltest. Ich finde auch die Makrokombinationen -> Und #(...) hilfreich, um einfache Funktionen zu schreiben, die Vektoren zurückgeben, z.

#(-> [%2 %1])
62
DaoWen

Wenn Sie #(...) verwenden, können Sie sich vorstellen, dass Sie stattdessen (fn [args] (...)), einschließlich die Klammern schreiben, die Sie direkt nach dem Pfund begonnen haben.

Ihr nicht funktionierendes Beispiel wird also in Folgendes konvertiert:

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

was offensichtlich nicht funktioniert, weil Sie versuchen, call die Zeichenfolge "Eh". Ihr Beispiel mit str funktioniert, weil Ihre Funktion jetzt (str s) Anstelle von (s) Lautet. (identity s) Wäre das nähere Analogon zu Ihrem ersten Beispiel, da es nicht zwingen würde, str.

Wenn Sie darüber nachdenken, ist es sinnvoll, da abgesehen von diesem völlig minimalen Beispiel jede anonyme Funktion irgendetwas aufruft. Es wäre also ein wenig dumm, eine andere verschachtelte Gruppe von Parens zu fordern, um tatsächlich zu funktionieren einen Anruf tätigen.

20
John Flatness