2016-08-14 3 views
2

다음 매크로가 작동 중임을 확인하십시오. 나는 일반적인 경우의 매개 변수 목록에서 a3을 떠날 경우xor에 대한 체계 매크로 정의

(define-syntax xor 
    (syntax-rules() 
    ((xor a1 a2) 
    (if a1 
     (false? a2) 
     (true? a2))) 
    ((xor a1 a2 a3 ...) 
    (let ((a (xor a1 a2))) 
     (xor a a3 ...))))) 

그러나 보인다, 그것은 제대로 작동하지 않습니다.

(define-syntax xor 
    (syntax-rules() 
    ((xor a1 a2) 
    (if a1 
     (false? a2) 
     (true? a2))) 
    ((xor a1 a2 ...) 
    (let ((a (xor a1 a2))) 
     (xor a ...))))) 

따라서 두 번째 경우의 줄임표가 정확히 무엇인지 궁금합니다.

1x. 생략 부호를 제외한 각 매개 변수 목록은 올바르게 실행하려면 고유해야합니다.

주어진 입력 예 : (xor #t #t #t), 첫 번째는 #t이고 두 번째는 #f입니다.

내가 사용하는 통역자는 mit-scheme입니다.

질문 2. 그리고 그것을 단락시킬 수 있습니까?

감사합니다.

+2

[라켓의 'oneof'기능의 기능 변형]의 사용 가능한 복제 (http://stackoverflow.com/questions/38820738/functional-variant-of-oneof-function-in-racket) –

+1

매크로로 이것을하는 것이 합리적입니까? 2-ary 확장은 첫 번째 인수와 관계없이 두 번째 인수를 평가해야하므로'(λ (a b) (a가 아닌 경우))'함수와 어떻게 다릅니 까? –

+0

@ JoshuaTaylor 맞습니다. 단락이없는 경우 함수로 정의하는 것이 좋습니다. 여기서 매크로로 시도해보고 생략 문제를 해결하려고하면 ** Q1 **를 참조하십시오. 실 웨스터 (Sylwester)의 말에 따르면, 단락 회로를 만드는 방법이 존재합니다. 그러면 매크로는이 경우 함수보다 더 유용합니다. – Ling

답변

1

줄임표는 두 번째 기호에 대해 알려줍니다. a2 ...은 0 개 이상의 요소가 될 수 있으며 다시 작동하기 위해 a2을 사용해야합니다. 두 번째 매크로에서 a2의 결과에는 되풀이 요소의 줄임표가 누락되어 a 이후에 ellipsis이 있으며 일치 패턴의 일부가 아니며 줄임표도 없습니다. 이 두 가지 사실로 인해 매크로가 유효하지 않게됩니다.

첫 번째 매크로는 두 요소와 일치하는 용어가 하나 있기 때문에 정확합니다. 두 번째 용어도 두 개의 용어와 일치하지만, 일치하는 첫 번째 패턴이 실행되기 때문에 두 번째 패턴에 대해 두 개 이상의 인수가 있다고 확신하기 때문에 두 개 요소는 적어도 하나의 요소 인 a3 ...과 일치합니다.

나는 true?이 무엇을위한 것인지 잘 모르겠습니다. 약간의 단순화 :

(define-syntax xor 
    (syntax-rules() 
    ((xor a1 a2) 
    (if a1 (not a2) a2)) 
    ((xor a1 a2 a3 ...) 
    (xor (xor a1 a2) a3 ...)))) 

(xor 1 2 3 4 5) ; ==> 5 (odd number of true values) 
(xor 1 2 3 4) ; ==> #f (even number of true values) 
(xor 1 2 3 4 #f) ; ==> #f (even number of true values) 
(xor 1 #f #f #f) ; ==> #t (odd number of true values) 

지금이 인수 식의 홀수 패리티를 계산합니다. 플립 플립 때문에 단락 될 수 없습니다. (xor #t #t #f #f #t) ; ==> #t에는 홀수 개의 참 인수가 있으므로 그것이 무슨 일을하는지에 관한 것이고, 데이지 체이닝 xor 로직 인 반면 사실은 하나의 진정한 로직 만 남았습니다. 당신이 결코 단락 당신이뿐만 아니라 동일한 일을하는 프로 시저를 사용할 수 수 있기 때문에 :

(define (xor . args) 
    (= (remainder (count values args) 2) 1)) 

(xor 1 2 3 4 5) ; ==> #t (odd number of true values) 
(xor 1 2 3 4) ; ==> #f (even number of true values) 
(xor 1 2 3 4 #f) ; ==> #f (even number of true values) 
(xor 1 #f #f #f) ; ==> #t (odd number of true values) 

백작은 SRFI-1 list library에서 찾을 수 있습니다.

xor의 또 다른 해석이 있습니다. 단락 회로가 작동하는 유일한 케이스이기 때문에이 질문을 읽을 때 첫 번째 질문입니다. 하나의 표현식이 참이면 true이고 그렇지 않으면 false입니다. 여기에서 두 번째 false 값이 발생하면 나머지 인수를 평가하지 않고 #f으로 단락시킬 수 있습니다.

(define-syntax xor 
    (syntax-rules() 
    ((_) #f) 
    ((_ a) a) 
    ((_ a b ...) 
    (if a 
     (not (or b ...)) 
     (xor b ...))))) 

(xor 1 2 3 4 5) ; ==> #f (more than one true value) 
(xor 1 2 3 4) ; ==> #f (more than one true value) 
(xor 1 2 3 4 #f) ; ==> #f (more than one true value) 
(xor 1 #f #f #f) ; ==> #t (only one true value) 

;; Slightly more complex version where 
;; the result is always the one true value or #f 
(define-syntax xor 
    (syntax-rules() 
    ((_) #f) 
    ((_ a) a) 
    ((_ a b ...) 
    (let ((tmp a)) 
     (if tmp 
      (and (not (or b ...)) tmp) 
      (xor b ...)))))) 

(xor 1 2 3 4 5) ; ==> #f 
(xor 1 2 3 4) ; ==> #f 
(xor 1 2 3 4 #f) ; ==> #f 
(xor 1 #f #f #f) ; ==> 1 (the actual true value, consistent) 

대부분의 알고리즘이 절차를 사용하여 어떠한 속도 처벌이되지 않습니다,하지만 난이 매크로는 매크로로 편리하게 할 수있는 몇 가지 상황이있을 수 있습니다 같아요. 값을 유지하지 않는 하나의 절차 버전은 다른 하나의 프로 시저 버전과 매우 유사합니다 :

(define (xor . args) 
    (= (count values args) 1)) 
+0

안녕하세요, 저는 단락 회로가 작동하는 방식에 대해 아직 조금 혼란 스럽습니다. 예를 들어'(xor #t #f #t #t)'를 고려하면, 이것은 실제로'# t '로 평가되어야하지만, 단락 작용으로 인해'# f'로 평가됩니다. 이렇게 잘못해서는 안됩니까? – Ling

+0

XOR을 사용하면 단락 회로가 이해되지 않습니다. ** (xor v0 ... vn) ** : ** (xor v0 ... vn-1) **의 값이 무엇이든 관계없이 ** vn **의 값이 필요합니다. 결과는이다. ** (와 v0 ... vn) ** 같은 단락은 ** (와 v0 ... vn-1) **이 * false * 인 경우에 당신이 알고 있음을 알기 때문에 작동합니다. ** vn **의 가치를 알 필요는 없으며 계산을 건너 뛸 수 있습니다. –

+0

* "하나의 표현식 만 참값이면 참값이 결과이고, 두 개의 인수가 참이면 나머지는 계산되지 않고 #f에 단락됩니다. * * XOR이 아닙니다. 예를 들어, ** (xor #t #t) = (xor (xor #t #t) #t) = (xor #f #t) = # t **. 그러므로 두 가지 사실을보고 나서 멈추고 전체 표현이 거짓이라고 결론 내릴 수 있습니다. XOR은 본질적으로 설정된 비트 수가 홀수인지 또는 짝수인지를 계산합니다 (패리티 비트). 그렇게하기 위해서는 모든 주장을 평가해야합니다. –

0

나는 공상 define-syntax을 사용하지만,이 어떤 도움을 줄 수있는 방법을 모르겠어요. 사람이 xor 대신 간단한 절차의 구문으로 정의해야하는 이유를 설명 할 수있는 경우

, 나는^_^알고 싶습니다

(define (xor a b . xs) 
    (cond [(and a b) #f] 
     [(empty? xs) (or a b)] 
     [else  (apply xor (or a b) (car xs) (cdr xs))])) 

(xor #t #f)    ; => #t 
(xor #t #t)    ; => #f 
(xor #t #f #f)   ; => #t 
(xor #t #f #f #t)  ; => #f 
(xor #f #f #f #f #f #t) ; => #t