Pregunta

parece que hay un límite en el número de parámetros de una función clojure puede tomar.

Al definir una función con más de 20 parámetros de recibo el siguiente:

#<CompilerException java.lang.RuntimeException: java.lang.RuntimeException: java.lang.Exception: Can't specify more than 20 params (NO_SOURCE_FILE:0) (NO_SOURCE_FILE:0)>

Obviamente esto se puede evitar, pero yo estaba golpeando este límite portar el modelo de ejecución de un DSL existente para clojure, y tengo construcciones en mi DSL como el siguiente, que por la expansión de macros se pueden asignar a funciones con bastante facilidad a excepción de este límite:

(defAlias nn1 ((element ?e1) (element ?e2)) number
"@doc features of the elements are calculated for entry into
      the first neural network, the result is the score computed by the latter"
(nn1-recall (nn1-feature00 ?e1 ?e2) (nn1-feature01 ?e1 ?e2) ... (nn1-feature89 ?e1 ?e2)))

que es una declaración DSL para llamar a una red neuronal con 90 nodos de entrada. Puede trabajar alrededor de ella, por supuesto, pero se preguntaba donde el límite viene. Gracias.

¿Fue útil?

Solución

En primer lugar, el límite sólo se aplica a argumentos posicionales requeridos ; siempre se puede utilizar el caso variable de aridad (& more-args en la firma de la función) para manejar tantos argumentos como se desea:

(defn foo [& args]
  (count args))

(foo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25)
;; returns 25

De hecho, a primera vista, & args es probable que sea la solución adecuada a su problema. (Por ejemplo, usted será capaz de asignar una función más de sus nodos de entrada recogidos en una secuencia, loop / recur sobre dicha secuencia etc - tiende a tener más sentido con un gran número de elementos similares de asignar nombres separados para cada uno de ellos.

(Tenga en cuenta que yo no pretendo saber la naturaleza de la DSL específico que está transcribiendo en Clojure o el tipo de problemas que está tratando con puntos, justo lo que sugiere que podrían ser de su interés. Si' hemos conseguido una situación muy funky, donde esto no parece aplicarse, tal vez usted puede proporcionar más detalles y vamos a ver si alguien aquí puede ofrecer algunos consejos útiles para tratar con ella en Clojure.)

En aras de la exhaustividad, se puede añadir el bit & args a una función que toma sus primeros 19 argumentos como argumentos posicionales requeridas:

(defn bar [a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 & as]
  (+ 19 (count as)))

(bar 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25)
;; returns 25

Tenga en cuenta que si especifica 20 argumentos posicionales y el arg & encima de eso, al parecer, la rareza se producirán.

En cuanto a la razón de ser, creo que esto tiene que ver con el hecho de que la JVM puede enviar a un método por el aridad de manera muy eficiente, por lo que la clase clojure.lang.Fn tiene el método invoke sobrecargado para arities hasta 20. No estoy del todo seguro de si podría ir más alto que eso, pero supongo que esto no es algo que la gente a menudo requieren que ... Quiero decir, seguro que encontrará cualquier API que especifica más de 20 argumentos posicionales a una función un poco sospechoso.

Otros consejos

La respuesta de Michal Marczyk le dice muy bien cómo moverse por el límite. Si está interrested en la razón de esta limitación, es posible que desee echar un vistazo a este pedacito de la fuente clojure: IFn

invoke ser un método java sobrecargado implementado por la interfaz de Ifn, Rich sobrecargado para soportar hasta 20 argumentos. Cuando se llama a una función en clojure, las llamadas implementación subyacente de invocación en el objeto función, un método que sólo admite hasta 20 argumentos.

Se podría sobrecargar a soportar más, pero dudo de la utilidad de tal cosa. Si usted tiene un montón de fuentes de entrada, que probablemente pueden ser tratados como una matriz de todos modos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top