2014-12-15 5 views
3

Clojure 1.6.0에 소개되었습니다. Java 프로젝트에 Clojure 기능을 일부 가져 오려고합니다. 불행히도 자바에서 조건부 함수 또는을 호출 할 때 예상대로 작동하지 않습니다.예기치 않은 동작이 clojure.java.api.Clojure

IFn and = Clojure.var("clojure.core", "and"); 
IFn or = Clojure.var("clojure.core", "or"); 

-- equivalent to (and true false) in clojure 
and.invoke(true,false); --> returns true rather than false??? 

-- equivalent to (or true false) in clojure 
or.invoke(true,false); --> returns null rather than true??? 

-- equivalent to (and true true) in clojure 
and.invoke(true,true); --> returns true as expected 

-- equivalent to (or true true) in clojure  
or.invoke(true,true); --> returns null rather than true??? 

나는 이것이 버그라는 것을 믿을 수 없다. 그래서 나는 API와 관련하여 상당히 근본적인 것이 빠져 있다고 생각한다. 그 원인이 무엇이든간에 그것은 혼란 스럽습니다. 누구든지 설명을 해줄 수 있다면 매우 감사 할 것입니다.

감사합니다.

매트.

답변

3

andor은 매크로이며 평가 규칙은 다소 다릅니다. 예를 들어, Clojure REPL에서 and을 평가하려고하면 CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)을 던집니다.

그래도 clojure.java.api.Clojure을 통해 사용할 수있는 방법이 있지만 작동하려면 매크로를 컴파일해야하므로 지금은 알지 못했습니다.

제가 생각할 수있는 최선의 선택은 eval을 사용하고 있지만 내가하고 싶은 것이 있는지 잘 모르겠습니다. 반면에, 좋은 이전 &&/|| 자바 연산자가 존재하는 경우 and/or을 사용해야하는 이유는 무엇입니까?

1

andor은 기능이 아닌 매크로입니다. 그들은 두 개 이상의 형식을 기대합니다 (예 : 심볼 또는 중첩 된 IPersistentLists의 목록). let*if의 조합으로 확장됩니다.

(clojure.walk/macroexpand-all '(and true false)) 
;returns: 
(let* [and__3941__auto__ true] 
     (if and__3941__auto__ 
     false 
     and__3941__auto__)) 

당신은 귀하를 대신하여 andor를 사용하는 Clojure의 경우 fn을 더 잘 할 수있다. 예를 들어, 콜렉션을 취할 :

(defn reduce-and [values] 
    (reduce #(and %1 %2) values)) 
(defn reduce-or [values] 
    (reduce #(or %1 %2) values)) 
+1

는'and'-줄이고'인'and'을 원래'or'의 단락의 의미를 풀어 or'이-줄일 것을 고려 때로는 의지합니다. –