2012-11-05 2 views
3

나는 Clojure를 배우고있다. 이 코드는 재귀 적으로 디렉터리를 걷기 위해 작성했습니다.Java 메소드를 호출하는 Fn을 얻는 방법은 무엇입니까?

(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory")) 

이유는 Clojure에서의 일류 함수로 .isDirectory을 사용할 수 없습니다? 이 코드를 다시 작성하는 더 좋은 방법이 있습니까?

답변

6

자바 메소드는 메소드를 호출 할 수 없기 때문에 클로저 함수가 아닙니다. 당신은 객체에 대한 메쏘드를 호출해야만하고 메쏘드가 기대하는 유형의 객체 여야 만합니다. 즉, java에서는 메소드를 정의 클래스에서 완전히 분리 할 수 ​​없습니다 (적어도 효율적이지는 않음).

# (.foo %)의 대안은 (memfn foo)가 될 것이고 # (...)이 도입 된 이후에는 아무도 더 이상 사용하지 않습니다.

1

sourcecode of file-seq (tree-seq을 사용)에서 어떻게 작동하는지 확인할 수 있습니다.

그건 그렇고 : 코드가 완벽하게 잘 작동합니다. REPL에서 File 대신 java.io.File을 사용해야하므로 Java 클래스를 알 수 있습니다.

7

주스트 (Juost)는 일류 클래스의 기능이 아닌 Java 메소드에 관한 부분입니다.

이 문제를 해결하기 위해 Java 기능을 Clojure 함수로 랩핑 (또는 이미 이것을 수행하는 라이브러리 찾기)하고 싶습니다. 그런 다음 관용적 인 1 급 방식으로 사용하기가 쉽습니다.

(defn directory? [^java.io.File file] 
    (.isDirectory file)) 

(defn list-files [^java.io.File file] 
    (.listFiles %1)) 

(tree-seq directory? list-files (File. "/my-directory")) 

이것은 코드 몇 줄 이상이지만, 다음과 같은 장점이 있습니다

  • 당신은
  • 이 마지막 코드는 청소기 (위와 같이) 반사를 방지하기 당신의 기능에 타입 힌트를 추가 할 수 있습니다 그리고 더 관용적 인
  • 당신은 이미 정답을받은 적이 있지만 조금 더 Clojure의 관용적 인 코드를 추가하는 기본 자바 상호 운용성
1

에서 멀리 추상화, 나는 또한 사용하십시오

#(.foo %) 
Joost Diepenmaat이 한 것처럼

(그러나 나는 그것이 간과되었을 수도 있다고 믿었습니다).

나는 또한 Listing files in a directory in Clojure을 읽을 것을 제안합니다.

관련 문제