[clojure] 클로저 : 감소 대 적용

나는 사이의 개념 차이를 이해 reduce하고를 apply:

(reduce + (list 1 2 3 4 5))
; translates to: (+ (+ (+ (+ 1 2) 3) 4) 5)

(apply + (list 1 2 3 4 5))
; translates to: (+ 1 2 3 4 5)

그러나 어느 것이 관용적 클로저입니까? 어떤 식 으로든 다른 점에서 많은 차이가 있습니까? 내 (제한된) 성능 테스트에서 reduce조금 더 빠릅니다.



답변

reduce그리고 apply물론 단지 동등한있는 가변 인수에 대응 케이스에 모든 인수를 볼 필요가 연관 기능 (궁극적 인 결과의 측면에서 반환). 그것들이 결과적으로 동등 할 때, 나는 그것이 일반적으로 apply완벽하게 관용적이지만, 많은 경우 reduce에 동등 하지만 눈 깜박임의 일부를 깎을 수 있다고 말하고 싶습니다 . 다음은 이것을 믿는 나의 근거입니다.

+reduce변수 자체의 경우 두 가지 이상의 인수로 구현됩니다. 실제로, 이것은 가변적, 연관 기능 reduce을 수행하기 위해 엄청나게 합리적인 “기본”방법처럼 보입니다. 아마도 internal-reduce마스터에서 최근에 비활성화 된 1.2 참신을 통해 일을 가속화하기 위해 최적화를 수행 할 가능성이 있습니다. 바라건대 미래에 다시 도입되기를 희망합니다. vararg의 경우에 도움이 될 수있는 모든 기능을 복제하는 것은 어리석은 일입니다. 이러한 일반적인 경우 apply에는 약간의 오버 헤드가 추가됩니다. (실제로 걱정할 필요는 없습니다.)

반면에 복잡한 함수는 일반적으로 구현할 수없는 최적화 기회를 활용할 수 있습니다 reduce. 다음 apply당신이 그 동안 활용할 수 있도록 것입니다 reduce실제로 느려질 수 있습니다. 실제로 후자의 시나리오 발생하는의 좋은 예에 의해 제공된다 str: 그것은 사용 StringBuilder내부적의 사용으로 크게 도움이됩니다 apply보다는 reduce.

그래서, apply의심 스러울 때 사용한다고 말하고 싶습니다 . 그리고 그것이 당신에게 아무것도 사지 않는다는 것을 알게되면 reduce(그리고 이것은 곧 바뀔 것 같지 않다), reduce당신이 그것을 느끼면 그 불필요한 불필요한 오버 헤드를 면도 하는 데 자유롭게 사용 하십시오.


답변

이 답변을보고있는 초보자
에게는 조심하지 마십시오.

(apply hash-map [:a 5 :b 6])
;= {:a 5, :b 6}
(reduce hash-map [:a 5 :b 6])
;= {{{:a 5} :b} 6}


답변

의견이 다양하다-더 큰 Lisp 세계에서, reduce더 관용적 인 것으로 간주된다. 먼저, 이미 논의 된 가변성 문제가 있습니다. 또한 일부 공통 Lisp 컴파일러는 apply인수 목록을 처리하는 방식으로 인해 매우 긴 목록에 적용될 때 실제로 실패 합니다.

그러나 내 서클의 클로저리스트들 사이 apply에서이 경우에 사용하는 것이 더 일반적 인 것 같습니다. 나는 더 쉽게 이해하고 선호합니다.


답변

+는 여러 인수에 적용 할 수있는 특별한 경우이므로이 경우에는 차이가 없습니다. Reduce는 임의의 긴 인수 목록에 고정 된 수의 인수 (2)를 예상하는 함수를 적용하는 방법입니다.


답변

나는 일반적으로 모든 종류의 컬렉션에서 작업 할 때 감소를 선호한다는 것을 알았습니다. 그것은 잘 수행되며 일반적으로 매우 유용한 기능입니다.

apply를 사용하는 주된 이유는 매개 변수가 다른 위치에서 다른 것을 의미하거나 초기 매개 변수가 몇 개 있지만 컬렉션에서 나머지를 얻으려는 경우입니다.

(apply + 1 2 other-number-list)


답변

이 특정 경우에는 reduce읽기 쉽기 때문에 선호합니다 .

(reduce + some-numbers)

시퀀스를 값으로 바꾸고 있음을 즉시 알고 있습니다.

applyI이 적용되고있는 기능을 고려해야한다 : “아, 그것은이다 +내가 … 단일 번호를 받고 있어요, 그래서 기능”. 약간 덜 간단합니다.


답변

+와 같은 간단한 기능을 사용할 때는 실제로 어떤 기능을 사용하든 상관 없습니다.

일반적으로 아이디어는 reduce누적 연산입니다. 누적 함수에 현재 누적 값과 하나의 새 값을 표시합니다. 함수의 결과는 다음 반복에 대한 누적 값입니다. 따라서 반복은 다음과 같습니다.

cum-val[i+1] = F( cum-val[i], input-val[i] )    ; please forgive the java-like syntax!

적용하려면 여러 스칼라 인수를 예상하는 함수를 호출하려고하지만 현재 콜렉션에 있으며 꺼내야합니다. 따라서 말하지 않고

vals = [ val1 val2 val3 ]
(some-fn (vals 0) (vals 1) (vals 2))

우리는 말할 수있다:

(apply some-fn vals)

그리고 다음과 같이 변환됩니다.

(some-fn val1 val2 val3)

따라서 “적용”을 사용하는 것은 시퀀스 주위의 “괄호 제거”와 같습니다.