2010-04-29 5 views
11

클로저 기능에 필요한 매개 변수 수에 제한이있는 것으로 보입니다. , 클로저 기능에 최대 20 개의 매개 변수 한계가있는 이유

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

는 분명히 이것은 피할 수 있습니다,하지만 난 Clojure에 대한 기존 DSL의 실행 모델을 포팅이 한계를 명중했다 : 20 개 이상의 매개 변수로 함수를 정의 할 때

나는 다음을받을 DSL이 문을입니다

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

와 신경망 전화 : 나는 매크로 확장하여이 제한을 제외하고 아주 쉽게 기능에 매핑 할 수있는 다음과 같은 내 DSL의 구조를 가지고 90 입력 노드. 물론 그 문제를 해결할 수 있지만 한계가 어디에서 비롯되는지 궁금해하고있었습니다. 감사합니다. .

+0

스티브 맥코넬 (Steve McConnell)의 "코드 컴플리트 (Code Complete)"옹호자는 부분적으로 프로그래밍 효율성 연구를 기반으로하고, 메소드가 7 가지 이상의 인수를 가져서는 안되며 최근에는 Robert C. Martin의 "Clean Code" 한계를 3으로 낮 춥니 다. 나는 인터페이스를 재 설계해야 할 때를 결정할 때 좋은 경험을 발견했으며, 3은 극단적 인 것처럼 보입니다. 예, 저는 매크로와 함께 모든 특별한 상황을 알고 있습니다. 단지 "일반"의 경우 20이 상당히 관대하다는 것을 지적합니다. –

+0

배열 등으로 뉴런을 만들고 함수에 seqs로 입력하십시오. 그리고지도를 줄이십시오 seqs? 이 같은? http://www.fatvat.co.uk/2009/06/back-propagation-algorithm-in-clojure.html – claj

답변

17

우선 제한은 에만 적용되며 위치 지정 인수는입니다. 당신이 원하는대로 당신은 항상 많은 인수를 처리하기 위해 (함수의 서명에서 & more-args) 변수 인수에 대응 케이스를 사용하여 다음을 수행 할 수 있습니다

(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 

사실, 첫눈에, & args는 정확하게 적합한 솔루션이 될 가능성이 당신의 문제. (예를 들어 시퀀스로 수집 된 입력 노드를 통해 함수를 매핑 할 수 있습니다. loop/recur 등) - 각 항목에 별도의 이름을 지정하는 것보다 많은 유사한 항목을 사용하는 것이 더 적합합니다. 그 (것)들.

(나는 Clojure로 옮기고있는 특정한 DSL의 성격 또는 당신이 취급하고있는 문제의 종류를 아는 척하지 않는다, 다만 당신에게 관심사일지도 모른 지 점을 건의하십시오. 이것이 실제로 적용되지 않는 펑키 상황이 발생하면 Clojure에서 더 자세한 정보를 제공 할 수 있으며 여기서 누군가가 Clojure에서 유용한 힌트를 제공 할 수 있는지 알 수 있습니다.)

완성을 위해를 추가 할 수 있습니다. 필요한 위치 인수로 처음으로 19 개 인수를 함수에 934,623,210 비트 : 당신이 20 개 위치 인수와 그 꼭대기에 & 인수를 지정하면, 분명히 불확실성이 계속 일어날 것

(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 

참고.

이론적으로는 JVM이 매우 효율적으로 메소드에 전달할 수 있다는 점과 관련이 있다고 생각합니다. clojure.lang.Fn 클래스는 최대 20 개의 요소에 대해 invoke 메소드가 오버로드됩니다. 그것보다 더 높을 수 있는지에 대해서는 충분히 확신하지만, 사람들이 자주 요구하는 것이 아니라고 생각합니다. 제 말은 확실히 의심스러운 함수에 대한 20 개 이상의 위치 인수를 지정하는 API를 찾습니다.

+0

감사합니다. & args 실제로 그것을 완벽하게 해결합니다. – GuyC

+2

단지 20 개의 위치 지정 args와 나머지 args를 동시에 가지고 있음 : Rich가 2 분 전에 고쳤던이 아리 티에 대해 함수의 몸체를 평가하지 않고 nil을 반환하게하는 버그가있었습니다. 따라서 1.2에는이 문제가 없습니다. –

11

Michal Marczyk의 답은 한계를 극복하는 방법을 잘 알려줍니다. 이 제한 때문에 인터럽트를당한 경우,이 비트의 클로저 소스를 한눈에 볼 수 있습니다.

Invoke는 Ifn 인터페이스에서 구현 한 Java 오버로드 된 메소드 인 Rich가 최대 지원을 위해 오버로드했습니다. 20 가지 주장. clojure에서 함수를 호출하면 기본 구현에서 함수 객체에 대한 호출을 호출합니다.이 메소드는 최대 20 개의 arg 만 지원합니다.

더 많은 것을 지원하기 위해 오버로드 할 수는 있지만 그러한 일의 유용성은 의심 스럽습니다. 입력 소스가 많은 경우 어쨌든 배열로 처리 할 수 ​​있습니다.

+0

Michal의 대답은 한계를 넘어서지만, IFn을 들으려면 참으로 흥미 롭습니다. 감사. – GuyC