2016-07-08 3 views
1

내 Clojure 코드에 자주 나타나는 형식이 있으며이를 단순화 할 수있는 방법이 있는지 알고 싶습니다. 여기 Clojure에서 조건부 바인딩 및 실행

는 연산의 결과가 조건에 일치하는 경우 작업 X는, 몇 가지 코드를 변수 Y에 결과를 결합하여 실행 않는다 "행동의 설명이다 여기

내가 지금 사용하고 구현의 :.

(let [op-result (op ...)] 
    (if-let [my-var (when (pred op-result) op-result)] 
    then else)) 

내가 달성하기 위해 노력하고있어에 대한 너무 자세한 것 같다. 사람이 (내 자신의 매크로를 작성 그렇다) 어떤 제안이 있습니까?

+4

"my-var"에 "op-result"를 생략 할 수 있기 때문에 간단한 '(if (pred op-result) then else)'만 쓸 수 있습니다. 아니면 당신의 본보기가 더 복잡한가? – ClojureMostly

답변

0

난 당신이 "다음"에 op-result를 사용하려면 같은데요 하지만 많은 프리디 케이트 함수 tions는 그들의 논쟁이 아닌 true을 반환합니다. 그래서 당신은 단순히이 쓸 수 없습니다 :

(and (pred x) x) 

당신은

(if-let [op-result (and (pred (op)) (op))] 
    op-result 
    false) 

쓸 수 그러나 (op) 비싼 경우,이 낫다 :

(if-let [op-result (pred (op))] 
    op-result ;maybe `true`, but you want `(op)` 
    false) 

당신이 원하는 핵심 표현은 다음과 같습니다

(if-let [op-result (let [x (op)] (and (pred x) x))] 
    op-result 
    false) 

물론 약간 지루한데, 그렇게 많이 필요하다면 매크로를 작성하는 것이 좋습니다.


나는 또 다른 접근 방식은 술어가 "truthy"하는 것입니다 가정 :

(defn truthy 
    "Given a predicate function, return a new function. 
    When the original predicate function returns true for some value, 
    the new function returns the value (instead of true). Else returns 
    false." 
    [pred] 
    (fn [v] 
    (and (pred v) v))) 

((truthy even?) 2) ; 2 
((truthy even?) 3) ; false 

(if-let [op-result ((truthy pred) (op))] 
    op-result ;use op-result 
    false) 

다시, 매크로 편리 할 수 ​​있습니다.


일부 Lisps에서 나는 (이맥스 리스프에서 라켓에 match, pcase) 패턴 매칭을 사용하십시오. 이들은 cond과 같은 형태입니다. 종종 원래 값을 바인딩하는 동안 테스트에 대한 조건부를 적용 할 수있게합니다. core.match이이 작업을 수행 할 수 있는지 또는이 작업을 단독으로 수행하려는 경우 확실하지 않습니다.


마지막으로, 나는 완전히 다른 사람이 같은 이미 나도 몰라 Clojure에서의 한 - 라이너로 존재 함을 지적 할 전망이다. :) 그러나 나는 아무도 가지고 있지 않았기 때문에 나는 대답을 시도 할 것이라고 생각했다.

+0

'(and (pred x) x)'의 문제점은'x '가 이미 어딘가에 묶여 있어야한다는 것입니다. 어딘가에 추가 어휘가 필요하거나 두 번 계산해야합니다. –

+0

정확합니다. 내가 볼 수있는 두 가지 접근법은 (a) 추가 "let"바인딩을 사용하거나, (b) "진리"방식으로 동작하는 조건자를 "강화"하는 것입니다. (함수는 인수의 바인딩이기 때문에 어느 정도는 동일하지만 이론적으로는 함수 응용의 관점에서'let '을 만들 수 있습니다. 그러나이 수준에서는 어느 쪽을 선호합니까?) 어느 쪽이 더 편리할까요? 매크로를 사용하지만 매크로를 작성하고 싶은 코드를 탐색하거나 시도하는 것이 좋습니다. –