Lisp 编程的正确方法?
我是 Common Lisp 的新手,发现自己利用了函数返回值的方式。以下是两个简单的例子:
(defun safe-avg (a b)
(and (numberp a) (numberp b) (/ (+ a b) 2)))
(defun safe-div (a b)
(and (numberp a) (numberp b) (> b 0) (/ a b)))
但我可以这样写(可以说更清楚):
(defun safe-avg (a b)
(if (and (numberp a) (numberp b))
(/ (+ a b) 2)))
(defun safe-div (a b)
(if (and (numberp a) (numberp b) (> b 0))
(/ a b)))
在我开始滥用这种习惯之前,我想知道做这样的事情的首选方法是什么以及其背后的原因。
I'm new to Common Lisp, and found myself taking advantage of way functions returns values. The following are to two trivial examples:
(defun safe-avg (a b)
(and (numberp a) (numberp b) (/ (+ a b) 2)))
(defun safe-div (a b)
(and (numberp a) (numberp b) (> b 0) (/ a b)))
But I could've written it like this (arguably clearer):
(defun safe-avg (a b)
(if (and (numberp a) (numberp b))
(/ (+ a b) 2)))
(defun safe-div (a b)
(if (and (numberp a) (numberp b) (> b 0))
(/ a b)))
I wanted to know what is the preferred method of doing something like this and the reasoning behind it, before I start abusing this habit.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于您不使用“else”分支,因此您可以使用
when
: ,它与: 相同,
它与您的版本相同,但更明确。
无论如何,这些在功能上都是等效的。我宁愿考虑如何使用这些功能。如果这样做,每次调用这些函数时都必须进行 null 检查,这很乏味。
最好通过类型声明、断言或显式
when
...signal
形式使用条件。然后,您可以为程序的整个部分定义处理程序并根据这些条件重新启动。进一步阅读:实用 Common Lisp,第 1 章19.。在这种情况下,我根本不会在这里处理这个:(
或者更确切地说,只使用
/
)。如果
/
获取了错误的参数,它将发出错误信号,然后您可以在外部处理该错误,您知道这可能意味着什么。Since you do not use the "else" branch, you could use
when
:which is the same as:
which is the same as your version, but more explicit.
Anyway, these are all functionally equivalent. I would rather think about how these functions are to be used. If you do it like this, you will have to do null checks each time you call these functions, which is tedious.
It would be better to use conditions, either through type declarations, through asserts, or through explicit
when
…signal
forms. You can then define handlers and restarts for these conditions for entire parts of your program. Further reading: Practical Common Lisp, ch. 19.In this case, I would not handle this here at all:
(or rather, just use
/
).If
/
gets the wrong arguments, it will signal an error which you can then handle outside, where you know what that could mean.第一种形式在习惯上是可以接受的。这不是有效使用
AND
返回值的最佳示例,因为第二种形式更清晰一些,但又不冗长。但您不应该害怕按预期使用 LISP!例如,朝着(不建议的)方向前进......有人可能会认为
if
语句的隐式“nil return”可能会令人困惑,并尝试并行if/else
结构更清晰:那很糟糕。而且你不想走那条路。因此,继续使用表达式并通过良好的评估来修剪代码量,并使用注释来弥补不足,以提醒其他人(和您自己)如果有任何不明显的事情,它是如何工作的。
The first form is idiomatically acceptable. It isn't the best example of using
AND
's return value effectively, since the second form is a little clearer without being any lengthier. But you shouldn't be afraid to use LISP as intended!For instance, going in an (inadvisable) direction...someone might argue that the implicit "nil return" of
if
statements could be confusing and try and parallelif/else
structure to be more clear:That's bad. And you don't want to go down that road. So go ahead and use the expressions and trim the amount of code with nice evaluations, and use comments to pick up the slack to remind others (and yourself) of how it works if there's anything non-obvious about it.