Macros 定义xor的scheme宏

Macros 定义xor的scheme宏,macros,scheme,lisp,mit-scheme,Macros,Scheme,Lisp,Mit Scheme,请注意,以下宏正在工作 (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

请注意,以下宏正在工作

(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

我使用的解释器是
mitscheme

Q2.是否可能使其短路


谢谢,

省略号告诉您一些关于第二个符号的信息<代码>a2…可以是零个或多个元素,您需要在重复的内容中使用
a2
,以使其工作。在第二个宏中,
a2
的结果缺少循环元素的省略号,并且在
a
之后有
省略号,它不是匹配模式的一部分,也没有省略号。这两个事实都使宏无效

第一个宏是正确的,因为您有一个匹配两个元素的项。您的第二个术语也匹配两个术语,但由于匹配的第一个模式已运行,您确信您的第二个模式有两个以上的参数,因为它匹配了两个且
a3…
至少是一个元素

我不确定
是真的吗?
是用来做什么的。稍微简化一下:

(定义语法xor
(语法规则()
((xor a1 a2)
(若a1(非a2)a2)
((异或a1 a2 a3…)
(xor(xor a1 a2)a3…)
(异或12345);==>5(真值的奇数)
(异或1234);==>#f(真值的偶数)
(异或1234#f);=>#f(真值的偶数)
(xor 1#f#f#f);=>#t(真值的奇数)
现在,这将计算参数表达式的奇偶校验。它不能短路,因为它是触发器<代码>(xor#t#t#f#f#t);=>#t
,因为它有奇数个真参数。这就是它所做的,虽然它是菊花链
xor
逻辑,但它并没有真正剩下一个真正的逻辑。因为你永远不会短路,你也可以使用一个程序来做同样的事情:

(定义(xor.args)
(=(余数(计数值参数)2)1))
(异或12345);==>#t(真值的奇数)
(异或1234);==>#f(真值的偶数)
(异或1234#f);=>#f(真值的偶数)
(xor 1#f#f#f);=>#t(真值的奇数)
可在中找到计数

还有另一种解释是xor,这是我读这个问题时想到的第一种解释,因为这是短路唯一起作用的情况。如果一个表达式为真,则该表达式为真,否则结果为假。在这里,当遇到第二个假值时,可以短路到
#f
,而不计算其余参数

(定义语法xor
(语法规则()
((35;)f)
((a)a)
(((a b…)
(如属
(不是(或b…)
(异或b…)(异或b…)
(异或12345);==>#f(多个真值)
(异或1234);==>#f(多个真值)
(异或1234#f);=>#f(多个真值)
(xor 1#f#f#f);=>#t(只有一个真值)
;; 稍微复杂一点的版本
;; 结果总是一个真值或#f
(定义语法xor)
(语法规则()
((35;)f)
((a)a)
(((a b…)
(让((tmp a))
(如果是tmp
(和(非(或b…)tmp)
(异或b…);(异或b…)
(异或12345);==>#F
(异或1234);==>#F
(异或1234#f);=>#F
(xor 1#f#f#f);=>1(实际真实值,一致)
大多数算法不会因为使用过程而受到任何速度损失,但我想在某些情况下,这个宏作为宏可能会很方便。不保留该值的程序版本与另一个的程序版本非常相似:

(定义(xor.args)
(=(计数值参数)1))

我不知道如何使用奇特的
定义语法,但这可能会提供一些帮助

如果有人能解释为什么
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

作为宏执行此操作是否有意义?二元展开式必须计算第二个参数,而不管第一个参数是什么,因此它与函数有何区别(lambda(ab)(如果a(非b)b))
?@JoshuaTaylor您是对的。如果没有短路,最好将其定义为一个函数。在这里,我只想把它作为一个宏来尝试,并试图解决省略号问题,请参见Q1。根据西尔维斯特的说法,似乎有一种方法可以使它短路。在这种情况下,宏将比函数更有益。@XOR中的凌霄短路没有意义。考虑(XOR V0…VN):不管(XOR V0…VN-1)的值是什么,仍然需要VN的值来知道最终结果是什么。例如,(和v0…vn)短路只起作用,因为你知道如果(和v0…vn-1)为假,那么你不需要知道vn的值,你可以跳过计算。嗨,我仍然对短路的工作原理有点困惑。例如,考虑<代码>(XOR→T→f→t→t)< /代码>,这应该真正地评价为<代码>→t>代码>,但是由于短路行为,它将被评估为<代码> f f>代码>。所以这不应该是错误的吗?短路对XOR没有意义。考虑(XOR V0…VN):不管(XOR V0…VN-1)的值是什么,仍然需要VN的值来知道最终结果是什么。例如,(和v0…vn)短路只起作用