在Scheme中,是否可以表示为布尔运算符的组合?

时间:2011-02-04 15:53:22

标签: scheme boolean-logic syntactic-sugar

根据andor的本地绑定的帮助)来表达notifor很容易。我想知道反过来是否正确。我天真的第一次尝试:

(if test conseq altern) => (or (and test conseq) altern)

但是,如果test不是#fconseq#f,则翻译的结果为altern,这是不正确的。

是否存在评估为正确值的转换,同时保持if的短路性质?

3 个答案:

答案 0 :(得分:4)

听起来你有一个很好的解释,为什么if的作用比andor多一点。但是如果你可以作弊并添加lambda来推迟实际结果:

(define-syntax-rule (if c t e) ((or (and c (lambda () t)) (lambda () e))))

答案 1 :(得分:2)

尝试(or (and test conseq) (and (not test) altern))作为一般模式。通过否定第二个test中的and,如果conseq为真,则确保外部分离为#ftest,或#f如果altern为假,则{∨test

答案 2 :(得分:1)

这与Eli Barzilay的答案相同,除了将其包装在lambda中之外,我将其包装在1个元素的列表中

(if test conseq altern) => (car (or (and test (list conseq)) (list altern)))

顺便说一下,2.5之前的Python有这个确切的问题。没有很好的方法可以在Python中编写条件表达式(即C中的test ? conseq : altern,这是Scheme中的if)。最简单的尝试是

test and conseq or altern

在大多数情况下有效,但在Python中conseq被视为false时失败(即False,0,空列表,空字符串等)。这是您在上面发现的确切问题。修复是将它包装在一个列表中(非空列表始终为true)并再次提取它:

(test and [conseq] or [altern])[0]

看起来很难看。这就是为什么他们在Python 2.5中添加了语法conseq if test else altern