Skip to content

Instantly share code, notes, and snippets.

@seeeturtle
Last active December 23, 2018 13:47
Show Gist options
  • Save seeeturtle/eff7bf49e682bd6ff30afb500098cfe2 to your computer and use it in GitHub Desktop.
Save seeeturtle/eff7bf49e682bd6ff30afb500098cfe2 to your computer and use it in GitHub Desktop.
Clojure Transducer 정리

Clojure Transducer 정리

일단 들어가기 전에 용어 설명부터 해보자.

  • reducing function: reduce를 할 때 인자로 넘기는 함수, 인자 두개(누적된 결과값과 새로운 값)를 받아 새로운 결과값을 반환한다.
  • transducer: reducing function을 받아서 새로운 reducing function을 만드는 함수. xform이나 xf로 불리기도 한다.

transducer는 다음과 형태를 가진다.

(fn [rf]
  (fn
    ([] ...)
    ([result] ...)
    ([result input] ...)))

실제 transducer를 만드는 함수를 보자.

(defn filter
  ...
  ([pred]
    (fn [rf]
      (fn
        ([] (rf))
        ([result] (rf result))
        ([result input]
          (if (pred input)
            (rf result input)
            result)))))
  ...)

위 코드를 보면 filterpred 하나만 인자를 받을 때 transducer를 반환한다는 것을 알 수 있다. 반환하는 transducer를 보면 rf를 인자로 받고 또다른 함수를 반환하는 것을 볼 수 있다. 즉, rfreducing function를 지칭하고 반환하는 또다른 함수는 또다른 reducing function인다.

다만 반환되는 함수는 그냥 reducing function은 아니다. 이 함수는 세개의 arity(위에서 [], [result], [result input])를 가지고 이들은 각각 목적을 지닌다.

  1. 초기화(init []): rf의 초기화 arity를 호출한다.
  2. 단계(step, [result input]): reducing function으로 rf의 단계 arity를 transducer에 알맞게 호출할거로 예상된다. 위 같은 경우 (pred input) 가 참일 경우에는 단계 arity를 호출하고 아니라면 호출하지 않는다.
  3. 완료(completion, [result]): 끝날때에 호출된다. rf의 완료 arity를 딱 한번 호출해야한다.

transduce 함수를 보면 이 과정이 어떻게 진행되는지 볼 수 있다.

(defn transduce
  ...
  ([xform f coll] (transduce xform f (f) coll)) ;(1)
  ([xform f init coll]
     (let [f (xform f) ;(2)
           ret (if (instance? clojure.lang.IReduceInit coll)
                 (.reduce ^clojure.lang.IReduceInit coll f init) ;(3)
                 (clojure.core.protocols/coll-reduce coll f init))] ;(3)
(f ret)))) ;(4)
  1. init 인자가 없으면 f의 초기화 arity를 호출함을 알 수 있다.
  2. 또한 transducerxformreducing functionf를 인자로 넘겨
  3. (xform f)로 reduce를 진행한다.
  4. 마지막으로 완료 arity를 호출하는 것도 볼 수 있다.

참고 자료

  1. 클로저 레퍼런스: https://clojure.org/reference/transducers (다만 오류가 있는 것 같다. 더 자세한 내용은 이슈를 보자)
  2. 클로저 소스코드
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment