Domanda

ci sembra essere un limite al numero di parametri funzione clojure può prendere.

Quando si definisce una funzione con più di 20 parametri viene visualizzato il seguente:

#<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)>

Ovviamente questo può essere evitato, ma mi è stato colpire questo limite il porting del modello di esecuzione di un DSL esistente per clojure, e ho costrutti nel mio DSL come la seguente, che per macro di espansione possono essere mappati a funzioni abbastanza facilmente ad eccezione questo limite:

(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)))

, che è una dichiarazione DSL per chiamare una rete neurale con 90 nodi di input. Può funzionare intorno ad esso, naturalmente, ma si chiedeva dove il limite proviene. Grazie.

È stato utile?

Soluzione

Prima di tutto, il limite si applica solo a argomenti posizionali richieste ; si può sempre utilizzare il caso variabili arity (& more-args nella firma della funzione) per gestire il maggior numero di argomenti come si vuole:

(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

In effetti, a prima vista, & args è probabile che sia esattamente la giusta soluzione al vostro problema. (Ad esempio, sarete in grado di mappare una funzione sopra i nodi di input raccolti in una sequenza, loop / recur di sopra di detta sequenza, ecc - tende a rendere più senso con un gran numero di oggetti simili che l'assegnazione di nomi separati per ognuno di loro.

(nota che io non pretendo di conoscere la natura dello specifico DSL voi sono trascrivere in Clojure o il tipo di problemi hai a che fare con, punti solo suggerendo che potrebbero essere di interesse per voi. Se si' hai una situazione davvero funky in cui questo non sembra applicare, forse è possibile fornire maggiori dettagli e vedremo se qualcuno qui in grado di offrire alcuni suggerimenti utili per affrontare in Clojure.)

Per ragioni di completezza, è possibile aggiungere il bit & args ad una funzione che prende i suoi primi 19 argomenti args posizionali necessarie:

(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

Si noti che se si specifica 20 args posizionali e l'arg & in cima a quello, a quanto pare stranezza ne conseguiranno.

Per quanto riguarda la logica, credo che questo abbia a che fare con il fatto che la JVM può inviare a un metodo da arity in maniera molto efficiente, quindi la classe clojure.lang.Fn ha il metodo di overload per invoke arietà fino a 20. Non sono del tutto certo se potesse andare più in alto di quello, ma suppongo che questo non è qualcosa che la gente richiedono che spesso ... Voglio dire, io certamente trovare qualsiasi API specificando oltre 20 argomenti posizionali a una funzione un po 'sospetto.

Altri suggerimenti

La risposta di Michal Marczyk ti dice molto bene come muoversi al limite. Se stai interrested nella ragione di questa limitazione, si potrebbe desiderare di dare uno sguardo a questo po 'di fonte clojure: IFN

invoke essere un metodo java overload implementato dall'interfaccia IFN Rich sovraccarico per supportare fino a 20 argomenti. Quando si chiama una funzione in clojure, le chiamate implementazione sottostante invoco su l'oggetto funzione, un metodo che supporta solo fino a 20 args.

Si potrebbe sovraccaricare di sostenere di più, ma dubito dell'utilità di tale cosa a. Se si dispone di un gruppo di sorgenti di ingresso, possono probabilmente essere trattata come una matrice in ogni caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top