2011-11-03 3 views
13

두 세트의 대칭 차이를 계산하는 함수를 작성했습니다 (4clojure 사이트의 문제 중 하나). 이 함수는 유닛 테스트를 통과했지만 코드가 중복되었다는 것을 감안하면 내가 원하는만큼 깨끗하지는 않습니다.Clojure에서 함수 내에서 함수를 정의하고 그 함수를 참조하려면 어떻게해야합니까?

(fn [x y] (set (concat 
    (keep-indexed #(if (nil? (get y %2)) %2) x) 
    (keep-indexed #(if (nil? (get x %2)) %2) y)))) 

분명히 내가 뭔가를 선호하는 것 :

은 diff 기능을 정의하고 "인라인"참조,하지만 난 하나 개 FN 블록에서 그 방법을 모르는되어
(fn [x y] (set (concat (diff x y) (diff y x)))) 

. 기능은 특히 그들이 객체는 최고 수준의 것들 Clojure에서의가 있다는 것입니다 Clojure의에게 LISP (그리고 일반적으로 기능적인 언어)을 만드는 기능

(fn [x y] 
    (let [diff (... function body here ...)] 
    (set 
    (concat (diff x y) (diff y x))))) 
+2

4clojure에서 다른 사람들의 답변을 볼 수 있습니다. 질문을 완료하면 자신의 시도를 정리할 수있는 방법을 알 수 있습니다. –

답변

21

let 또는 letfn를 사용합니다. (defn name [arg] ...)으로 함수를 만들면 함수를 빌드 한 다음 var에 저장하므로 나중에 프로그램의 어느 위치에서나 찾을 수 있습니다. 다음과 같이 많이 사용합니다.

(def name (fn [arg] ...)) 

이제는 이름에 널리 액세스 할 수있는 기능이 포함되어 있습니다. 함수가 vars에 저장 될 필요는 없습니다 (특히 함수 내에 만 필요한 경우). 이 경우 매트 펜윅 (Matt Fenwick) 응답과 같이 함수를 로컬 이름에 바인딩하는 것이 더 적합합니다.

(let [name (fn [agr] ...)] ...) 

letfn 매크로이 더 우아하게. 중요한 부분은 함수가 사물에 저장되는 객체라는 것을 이해하고 사용자의 필요에 맞는 컨테이너를 선택할 수 있습니다.

10

하나 :

+1

왜 "중요한 것은 기능이 ** 사물에 저장되어있는 ** 사물임을 이해하는 것입니다"라고 말했습니까? "객체"라고 말하면 누군가가 당신이 객체 지향적 인 의미에서 객체에 대해 이야기하고 있다고 생각하게 할 수 있습니다. 소문자 "객체"는 여기 있다고 생각합니다. (나는 Clojure가 많은 것들이 OO 클래스와 객체로 구현 된 JVM에서 구현된다는 것을 알고 있지만 새로운 Clojurian은 구현 세부 사항을 반드시 고려해야한다고 생각하지 않는다.) –

관련 문제