조건부 조건에 대한 "and"vs "when"


13

답변 에 대한 의견에 대한 후속 조치 입니다. 다음 코드 비트는 동일 해 보입니다.

(and a b)

(when a b)

물론 and당신은 더 많은 조건을 넣을 수 있습니다 : (and a b c d)수단을(when (and a b c) d)

나는 when분기를 표현 하는 데만 사용하는 경향이 있습니다 . 실제 차이점이 있습니까? 둘 중 하나를 사용하는 것이 낫습니까?

나는 Emacs의 C 소스를 가지고 있지 않다. andC 함수입니다. when로 확장되는 매크로 if이며 그 자체가 C 함수입니다.


"물론과하자"는 "물론`과`하자"여야하지만, 이는 단지 2 개의 문자 변경 일 뿐이며 편집이 허용되지 않습니다. 재정의는 없습니다.
Harvey

답변:


18

TL; DR : when 부작용에 관한 것 and입니다. 순수한 부울 식입니다.

당신은 눈치 챘을,로 andwhen구문 만 다른,하지만 그렇지 않으면 완전히 동일합니다.

구문상의 차이는 매우 중요 하지만 첫 번째 인수 형식을 제외한 모든 when것을 암시 적 progn으로 감 쌉니다 . progn본질적으로 필수적인 기능입니다. 마지막 신체 형태를 제외한 모든 신체 부작용을 평가하여 그들이 반환 한 값을 버립니다.

따라서 when가장 중요한 형태의 가치 만 실제로 신체에 중요하기 때문에 부작용이있는 형태를 포장하는 것이 주된 목적입니다.

and반면에, 주어진 인수 형식의 반환 값을 보는 것이 주 목적인 순수한 함수입니다. 인수를 명시 적으로 감싸지 않는 한 progn모든 인수 형식의 값이 중요하며 값이 무시되지 않습니다. .

따라서, 사이의 진정한 차이 andwhen문체입니다 : 당신이 사용하는 and순수 부울 표현식 및 when측면 초래 형태의 주위에 경비를 넣어.

따라서 이들은 나쁜 스타일입니다.

;; `when' used for a pure boolean expression
(let ((use-buffer (when (buffer-live-p buffer)
                    (file-exists-p (buffer-file-name buffer)))))
  ...)

;; `and' used as guard around a side-effecting form
(and (buffer-file-name buffer) (write-region nil nil (buffer-file-name buffer)))

그리고 이것들은 좋습니다 :

(let ((use-buffer (and (buffer-live-p buffer)
                       (file-exists-p (buffer-file-name buffer)))))
  ...)

(when (buffer-file-name buffer)
 (write-region nil nil (buffer-file-name buffer)))

나는 어떤 사람들이 이것에 동의하지 않고 행복하게 and부작용을 지키기 위해 사용한다는 것을 알고 있지만, 이것이 실제로 나쁜 스타일이라고 생각합니다. 이유는 다음과 같은 여러 가지 형태입니다. 구문 문제 . 그렇지 않다면, 우리 if는 Emacs Lisp에서 실제로 의미 적으로 유일하게 필요한 조건부 양식 인을 사용합니다. 다른 모든 부울 및 조건부 양식은의 용어로 작성할 수 있습니다 if.


2
IMO (즉, 스타일 I의 사용) and에 관한 것입니다 반환 값에 대한 배려 . 반드시 부작용을 사용하는 것은 아닙니다. 내 프로그램이 반환 값을 신경 쓰면을 사용 and합니다. 그렇지 않으면를 사용 when합니다. IOW, 나는 부작용 when 에만 사용 하지만 prognargs 중 하나에서를 사용할 수도 있습니다 and. 그것은하지 그 여부에 대해, 반환 값 문제 여부에 관하여 혼자 문제.
Drew

5
and내가 아는 Lisp의 기능이 아닙니다. 이맥스 리스프 (Emacs Lisp)에서는 특수한 형태이며, 공통 리스프 (Common Lisp)에서는 단락 동작이있을 것으로 기대되기 때문에 매크로입니다.
Mark Karpov

2
@lunaryorn, 그렇습니다. 그것은 실제로 관련이 없지만 사실입니다. 그래서 그것이 and함수가 아닌 함수 라고 쓰는 것이 잘못되었다고 생각합니다 . 사실이 질문과 얼마나 관련이 있는지는 중요하지 않으므로 항상 올바른 용어를 사용해야합니다.
Mark Karpov

2
글쎄, 나는“모든 논증 형식의 가치가 중요하다”는 것이 그 해석과 일치하지 않는다고 생각합니다. 어떤 형식도 그 가치를 버리기 위해 평가되지 않는다고 말함으로써 더 잘 표현 될 수있었습니다.
Harald Hanche-Olsen

3
다소 OT이지만 : 차이점은 Lisps의 문체적인 것 이상 nil입니다. "false", "공백 목록", "void"등을 모두 의미 하지는 않습니다 . 예를 들어 Scheme 및 Racket에서 when이다 void(즉, "아니오 의미")에 대한 반면, and그것이 #f( "거짓"). 이것은 Elisp에게는 N / A이지만 Lisp 일반인이 고려할만한 것입니다.
Greg Hendershott

4

내가 그 말에 의해 시작하자 (and a b)(when a b)같은 일을 당신의 예에서 : 먼저 a평가됩니다. b경우 평가 a입니다 진정한 # .

그러나 andwhen다른 일에 사용됩니다.

  • 당신이 사용하는 것이 (and a b)반환하는 진정한 #을 경우 BOTH a하고 b있는 사실 # (또는 비 무기 호); 와 nil그렇지.

  • 사용 (when a b)하거나 더 정확할 것입니다.

    (when a
       ;; do something like b
       )
    

    당신이 "B"코드가 실행하고자 할 때 경우에만 경우가 a있습니다 사실 # .


다음은 사용 예입니다 whenand함께이 :

(when (and a b)
   (do-c))

위 함수는 do-c만 둘 경우라고 a하고 b있습니다 사실 # .


연구를위한 참고 문헌

# true에 대한 모든 참조 는 부울 TRUE를 나타냅니다.


3
andt모든 인수가 0이 아닌 경우 마지막 인수의 값을 반환 합니다.
의미있는 사용자 이름

1
에 의해 t부울 TRUE 또는 non-nil을 의미했습니다. 고마워, 나는 내 대답에서 그것을 분명히 할 것입니다.
Kaushal Modi

나는 당신의 대답이 내가 이미 질문에 언급 한 것보다 훨씬 더 나아 가지 않는다고 생각합니다. 나는 둘 다 무엇을하는지 알고 있으며, 당신이주는 마지막 예는 이미 내 질문 ( (when (and a b) c))에 나타납니다 . 또한 그것이 어떻게 일반적으로 사용되는지 에 대한 부분 and과 방법에 대한 부분 when이지만이 질문의 가장 큰 근거는 종종 다른 방식으로 사용된다는 사실이었습니다 (예를 들어 내 질문에 연결된 답변 참조).
Clément

순수 기능성 구조체 포인트의보기에서 종료되지 않는 평가를위한 것이며, 그리고 직접 기호 및 부울 로직이다. 함수형 프로그래밍에는 이러한 구별이 필요합니다. 명령형 프로그래밍은 이것을 퍼지합니다.
Emacs 사용자

1
"부울 true"가 "true"보다 명확하지 않다고 생각합니다.
YoungFrog
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.