Warum können wir in Clojure keine verschachtelten Kurzfunktionen schreiben?

11

Ich habe heute versucht, einen Clojure-Ausdruck mit verschachtelten Kurzfunktionen zu bewerten, aber das ließ mich nicht.

Der Ausdruck war:

(#(+ % (#(+ % (* % %)) %)) 5) ; sorry for the eye bleed

Die Ausgabe war:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage
Lincoln Bergeson
quelle
2
Ich finde, dass es eine gute Sache für Clojure ist, solchen Code nicht schreiben zu können.
Simon Bergot
3
Weil es deine Augen bluten lässt.
Michael Shaw
Benötigen Sie nicht (# (+% 1 (# (+% 2 (*% 3% 4))% 5)) 5)?
innova

Antworten:

5

Sie würden wissen, dass% zur inneren Funktion gehört. Der Nachteil ist, dass Sie den Zugriff auf% in der äußeren Funktion verlieren würden.

Verwenden Sie fn [x]stattdessen die Syntax.

Robert Harvey
quelle
1
So? Die meiste Zeit brauche ich keinen Zugang zum %äußeren fn, und zu den Zeiten, auf die Sie es getan haben, könnten Sie zurückgreifen (fn), richtig?
Zaz
10

Es ist völlig willkürlich; Der Parser enthält einige Zeilen, die ihn explizit deaktivieren. Wenn Sie diese Zeile bearbeiten, können Sie anonyme Funktionen verschachteln, die genau so funktionieren, wie Sie es erwarten.

Insbesondere die Zeilen 634-635 in https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java

public static class FnReader extends AFn{
    public Object invoke(Object reader, Object lparen) {
        PushbackReader r = (PushbackReader) reader;
        if(ARG_ENV.deref() != null) // <-- line 634
            throw new IllegalStateException("Nested #()s are not allowed");
        // ...
Amara
quelle
Könnten Sie die Zeile im Parser identifizieren und zeigen, dass der Code neu geschrieben wurde, um keine anon verschachtelte Funktion zu haben, und dass der Code mit der aus dem Parser entfernten Zeile und einer anon verschachtelten Funktion genauso funktioniert?
2
@ MichaelT: Los geht's. und Sie können es einfach testen; Dies ist einfach, da Sie sie zur Laufzeit ausschalten können. Der Clojure-Parser ist wirklich leicht zu hacken
Amara
4
Nun, nicht ganz willkürlich; Wenn Rick Hickey nicht nur einen willkürlichen Tag hatte, muss es einen Grund gegeben haben, warum er ihn dort hineingelegt hat, und Sie scheinen nicht zu wissen, was dieser Grund ist. Duh.
Robert Harvey
Wow, was für ein Fund! Schön - +1.
Würde diese Änderung zu mehrdeutigen Analysen verschachtelter Methoden führen? Ich bin gespannt darauf, dass eine fn [x]Neufassung des OP-Codes die gleiche Funktionalität wie eine modifizierte Clojure-Version haben würde. Gibt es außerdem Probleme mit der Portabilität des Clojure-Codes?
3

Sie können anonyme Funktionen der Sorte (fn [params] (body)) verschachteln. Nur die # -Syntax unterstützt keine Verschachtelung.

WolfeFan
quelle