2010-04-29 13 views
11

için en fazla 20 parametre sınırı var. , Neden clojure işlevinin alabileceği parametrelerin sayısı için bir sınırlama var gibi görünüyor, bir clojure işlevi

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

Açıkçası bu önlenebilir, ama Clojure için varolan DSL yürütülmesi modeli taşıma bu sınırı vururkenbir: 20'den fazla parametreleri ile bir işlev tanımlarken

Aşağıdakileri almak DSL deyimi ise

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

ile bir sinir ağı çağırmak için: ve ben makro genişleme ile bu sınırın dışında oldukça kolay fonksiyonları eşlenebilir aşağıdaki gibi benim DSL açıklayıcı yapılar var 90 giriş düğümleri. Elbette etrafta çalışabilir, ancak sınırın nereden geldiğini merak ediyordum. Teşekkürler.

+0

Stil için bir ilgi notu gibi: Steve McConnell'in "Kod Tamamlandı", kısmen programlama verimliliği çalışmalarına dayanarak, bir yöntemin asla 7'den fazla argümana ve daha yakın zamanda Robert C. Martin'in "Temizlik Kodu" na sahip olmaması gerektiğini savunuyor. limiti 3 kadar düşük bir değere ayarlar. 7 bir arayüzün ne zaman yeniden yapılandırılacağına karar vermek için iyi bir kural kuralı buldum, 3 ise biraz aşırı görünüyor. Evet, makro ve tüm özel durumlarınızdan haberdarım. Sadece "genel" durum için, 20 oldukça cömerttir. –

+0

Nöronlarınızı dizilerle veya başka bir şeyle oluşturun ve onları seqs işleviyle besleyin. Ve seqleri harita-azaltın mı? Böyle bir şey mi? http://www.fatvat.co.uk/2009/06/back-propagation-algorithm-in-clojure.html – claj

cevap

17

Her şeyden önce, sınır yalnızca gerekli konumsal argümanlar için geçerlidir; istediğiniz kadar her zaman gibi birçok argüman işlemek için (işlevin imzası & more-args) değişken Arity durumda kullanabilirsiniz için:

(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 

Aslında, ilk bakışta, & args tam olarak doğru çözüm olması muhtemeldir senin sorun. (Örneğin, bir dizi içine toplanan giriş düğümleri üzerinde bir işlevi eşleyebileceksiniz, loop/recur, vb. - her biri için ayrı adlar atamaktan çok daha fazla benzer öğelerle daha anlamlı olma eğilimindedir.

(Not: Clojure'a yazdığınız belirli DSL'nin doğasını veya uğraştığınız türdeki sorunları bilmek istemediğimi unutmayın, sadece ilginizi çekebilecek noktalar öneririm. Eğer bu işlemin uygulanmadığı durumlarda gerçekten korkak bir durumunuz varsa, belki daha fazla ayrıntı sağlayabilirsiniz ve burada birisinin Clojure'da bununla ilgili olarak yararlı ipuçları sunabileceğini göreceğiz.)

tamlığı uğruna,ekleyebilirsiniz Gerekli pozisyonel args olarak ilk 19 argüman alan bir işleveBit: 20 pozisyonel args ve bunun üzerine & arg belirtirseniz, görünüşe garabeti doğmak edeceğini

(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 

Not.

gerekçe gelince, bu clojure.lang.Fn sınıf arities için aşırı invoke yöntemi vardır böylece JVM değilim kadar 20'ye, çok verimli bir Arity tarafından bir yönteme sevk edebilir gerçeği ile ilgisi var inan Bundan daha fazla gidebileceğinden tamamen emin olabilirsiniz, ama sanırım bu insanların sık sık ihtiyaç duyduğu bir şey değil ... Yani, kesinlikle 20'den fazla konumsal argüman belirten herhangi bir API'yi biraz şüpheli bir işleve yolluyorum.

+0

Teşekkürler & args gerçekten mükemmel şekilde adreslenir. – GuyC

+2

Sadece bir not: 20 pozisyonel args ve rest args aynı anda sahip: Zengin bir kaç dakika önce bu fonksiyonun bedenini değerlendirmek için, bu ariteyle değerlendirilmeksizin döndürülmesine neden olan bir hata vardı. Böylece, 1.2 bu sorun olmayacaktır. –

11

Michal Marczyk'ün cevabı size sınırı nasıl aşacağınızı çok iyi anlatıyor. Bu sınırlama nedeniyle bir araya geldiyseniz, bu clojure kaynağından bir bakış atmak isteyebilirsiniz: IFn

Ifn arabirimi tarafından uygulanan bir java aşırı yüklenmiş yöntem olma çağrısı, 20 argüman. Clojure işlevini çağırdığınızda, temel uygulama, işlev nesnesinde yalnızca 20 satıra kadar destek veren bir yöntem çağırır.

Daha fazla desteği desteklemek için aşırı yükleyebilirsiniz, ancak böyle bir şeyin yararlarından şüphe duyuyorum. Bir sürü giriş kaynağınız varsa, muhtemelen bir dizi olarak ele alınabilir.

+0

Michal´ın cevabı beni limitler etrafında döndürüyor, ama aynı zamanda IFN’ye göz atmak da ilginç. Teşekkürler. – GuyC