¿Por qué no podemos escribir funciones abreviadas anidadas en Clojure?

11

Traté de evaluar una expresión Clojure con funciones abreviadas anidadas hoy, y no me lo permitió.

La expresión fue:

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

El resultado fue:

IllegalStateException Nested #()s are not allowed  clojure.lang.LispReader$FnReader.invoke (LispReader.java:630)
...and a bunch of other garbage
Lincoln Bergeson
fuente
2
Me parece que no poder escribir dicho código es algo bueno para clojure.
Simon Bergot el
3
Porque hace sangrar tus ojos.
Michael Shaw
¿No necesita (# (+% 1 (# (+% 2 (*% 3% 4))% 5)) 5)?
innova

Respuestas:

5

Sabrías que% pertenece a la función interna. El inconveniente es que perdería el acceso al% en la función externa.

Use la fn [x]sintaxis en su lugar.

Robert Harvey
fuente
1
¿Entonces? La mayoría de las veces no necesito acceso al %exterior de la fn, y en las veces que lo hizo, podría recurrir a (fn), ¿verdad?
Zaz
10

Es completamente arbitrario; Hay un par de líneas en el analizador que lo desactivan explícitamente. Si edita esa línea, puede tener funciones anónimas anidadas, y actúan exactamente como cabría esperar.

específicamente, líneas 634-635 en 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
fuente
¿Podría identificar la línea en el analizador y demostrar que el código reescrito para no tener una función anidada y el código con la línea eliminada del analizador y una función anidada funciona igual?
2
@MichaelT: ahí lo tienes. y puedes probarlo; es fácil de hacer, ya que puede cambiarlos en tiempo de ejecución. el analizador de clojure es realmente fácilmente pirateable
amara
44
Bueno, no completamente arbitrario; a menos que Rick Hickey estuviera teniendo un día arbitrario, debe haber una razón por la que lo puso allí, y no parece saber cuál es esa razón. Duh
Robert Harvey
¡Qué hallazgo! Niza - +1.
¿Causaría este cambio algún análisis ambiguo de métodos anidados? Tengo curiosidad de que una fn [x]reescritura del código del OP tenga una funcionalidad idéntica a una versión modificada de clojure. Además, ¿habría algún problema con la portabilidad del código clojure?
3

Puede tener funciones anónimas anidadas del tipo (fn [params] (body)). Solo la sintaxis # no admite el anidamiento.

WolfeFan
fuente