在Scheme中,if可以表示为布尔运算符的组合吗?
很容易用 if
来表达 and
、or
和 not
(在本地人的帮助下)绑定或
)。我想知道相反的情况是否成立。我天真的第一次尝试:
(if test conseq altern) => (or (and test conseq) altern)
但是,如果 test
不是 #f
并且 conseq
是 #f
,则翻译计算结果为 altern
,这是不正确的。
是否有一种翻译可以在保持 if
的短路性质的同时计算出正确的值?
It is easy to express and
, or
, and not
in terms of if
(with an assist from a local binding for or
). I'd like to know if the reverse is true. My naïve first attempt:
(if test conseq altern) => (or (and test conseq) altern)
However, if test
is non-#f
and conseq
is #f
, the translation evaluates to altern
, which is incorrect.
Is there a translation that evaluates to the correct value while maintaining the short-circuit nature of if
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
听起来你有一个很好的解释为什么
if
的作用比and
和or
多一点。但如果您可以作弊并添加 lambda 来延迟实际结果:Sounds like you have a good explanation why
if
is doing a little more thanand
andor
. But if you could cheat and add alambda
to delay the actual result:尝试使用
(or (and test conseq) (and (not test)altern))
作为一般模式。通过对第二个and
中的test
求反,可以确保外部析取要么是conseq
∨#f
iftest
为 true,或者如果test
为 false,则#f
∨altern
。Try
(or (and test conseq) (and (not test) altern))
as the general pattern. By negatingtest
in the secondand
, it ensures that the outer disjunction will be eitherconseq
∨#f
iftest
is true, or#f
∨altern
iftest
is false.这与 Eli Barzilay 的答案相同,只是我没有将其包装在 lambda 中,而是将其包装在 1 元素列表中
顺便说一句,2.5 之前的 Python 确实存在这个问题。在Python 中没有好的方法来编写条件表达式(即C 中的
test ? conseq :altern
,这就是Scheme 中的if
)。最简单的尝试在大多数情况下都有效,但当 conseq 在 Python 中被认为是 false 时(即 False、0、空列表、空字符串等),就会失败。这正是您在上面发现的问题。解决方法是将其包装在一个列表中(非空列表始终为真)并再次提取它:
这看起来很难看。这就是为什么他们在 Python 2.5 中添加了语法
conseq if test else altern
。This is the same as Eli Barzilay's answer, except instead of wrapping it in a lambda, I wrap it in a 1-element list
By the way, Python prior to 2.5 had this exact problem. There was no nice way to write a conditional expression (i.e.
test ? conseq : altern
in C, which is whatif
in Scheme is) in Python. The simplest attempt waswhich worked in most cases, but failed when
conseq
is considered false in Python (i.e. False, 0, empty list, empty string, etc.). Which is the exact problem you discovered above. The fix was to wrap it in a list (non-empty lists are always true) and extract it again:which looks ugly. Which is why they added the syntax
conseq if test else altern
in Python 2.5.