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

发布于 2024-10-15 19:23:01 字数 404 浏览 2 评论 0原文

很容易用 if 来表达 andornot(在本地人的帮助下)绑定)。我想知道相反的情况是否成立。我天真的第一次尝试:

(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我不在是我 2024-10-22 19:23:01

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

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

Sounds like you have a good explanation why if is doing a little more than and and or. But if you could cheat and add a lambda to delay the actual result:

(define-syntax-rule (if c t e) ((or (and c (lambda () t)) (lambda () e))))
与往事干杯 2024-10-22 19:23:01

尝试使用 (or (and test conseq) (and (not test)altern)) 作为一般模式。通过对第二个 and 中的 test 求反,可以确保外部析取要么是 conseq#f if test 为 true,或者如果 test 为 false,则 #faltern

Try (or (and test conseq) (and (not test) altern)) as the general pattern. By negating test in the second and, it ensures that the outer disjunction will be either conseq#f if test is true, or #faltern if test is false.

狼亦尘 2024-10-22 19:23:01

这与 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

在大多数情况下都有效,但当 conseq 在 Python 中被认为是 false 时(即 False、0、空列表、空字符串等),就会失败。这正是您在上面发现的问题。解决方法是将其包装在一个列表中(非空列表始终为真)并再次提取它:

(test and [conseq] or [altern])[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

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

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 what if in Scheme is) in Python. The simplest attempt was

test and conseq or altern

which 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:

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

which looks ugly. Which is why they added the syntax conseq if test else altern in Python 2.5.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文