2016-08-14 4 views
2

Обратите внимание, что работает следующий макрос.определить макрос схемы для 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 ...))))) 

Однако, кажется, если я оставлю вне 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 ...))))) 

Таким образом, мне интересно, что происходит именно с эллипсисом во втором случае.

Q1. Означает ли это, что каждый список параметров, исключая эллипсис, должен быть уникальным для его правильной работы?

Например, данный ввод (xor #t #t #t), первый будет производить #t, тогда как второй будет производить #f.

Переводчик, которого я использую, является mit-scheme.

Q2. И можно ли короткое замыкание?

Спасибо,

+2

Возможный дубликат [функционального варианта «oneof» функции в Ракетка] (http://stackoverflow.com/questions/38820738/functional-variant-of-oneof-function-in-racket) –

+1

Имеет ли смысл делать это как макрос вообще? 2-арное расширение должно оценивать второй аргумент независимо от первого, так как он отличается от функции '(lambda (a b) (если a (not b) b))'? –

+0

@JoshuaTaylor Вы правы. Лучше определить его как функцию, если нет короткого замыкания. Здесь я просто хочу попробовать его как макрос и попытаться решить проблему с многоточием, см. ** Q1 **. И, согласно Сильвестру, похоже, существует способ сделать его короткое замыкание. Тогда макрос будет более полезен, чем функция в этом случае. – Ling

ответ

1

эллипсов говорит кое-что о втором символе. a2 ... может быть ноль или более элементов, и вам нужно использовать a2 в том, что повторяется для его работы. В вашем втором макросе результат с a2 отсутствует эллипсис для повторяющихся элементов, и у вас есть ellipsis после a, который не является частью шаблона соответствия, а также не имеет многоточия. Оба эти факта делают макрос недействительным.

Первый макрос правильный, поскольку у вас есть один термин, который соответствует двум элементам. Второй член также совпадает с двумя терминами, но поскольку первый шаблон, который соответствует, выполняется, вы уверены, что у вас есть более двух аргументов для второго шаблона, так как он соответствует двум с 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) 

Count можно найти в SRFI-1 list library.

Существует еще одна интерпретация xor, и это первый случай, когда я прочитал этот вопрос, так как это единственный случай, когда работает короткое замыкание. Это утверждение истинно, если одно выражение истинно, иначе результат будет ложным. Здесь, когда вы встретите второе ложное значение, вы можете короткое замыкание на #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 #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 
Смежные вопросы