就是if的THEN参数为t的情况:
(if (foo)
t
(bar))
改写成or
形式:
(or (foo)
(bar))
这两种写法哪种更好?
就是if的THEN参数为t的情况:
(if (foo)
t
(bar))
改写成or
形式:
(or (foo)
(bar))
这两种写法哪种更好?
沒有,
我才明白过来……第二种写法不就是short-cut么……
当 (foo)
返回 Non-nil 时,两者的返回值不同。
(if 1 t 2)
;; => t
(or 1 2)
;; => 1
下面两者等价(假设 tmp
不会影响 bar
)
(or (foo)
(bar))
(let ((tmp (foo)))
(if tmp
tmp
(bar)))
如果不考虑foo为non-nil时的返回值,那么可否认为这两个是等价的?
如果 foo
为 nil
,两者都返回 bar
,且都依次执行过 foo
/ bar
,所以可以认为它们效果相同。
谢谢回答。
所以我不需考虑foo为non-nil时的返回值(此函数的non-nil具体值无意义,或者foo必定返回t/nil),那么如果foo为non-nil时,两者都不会返回bar,同时都只有foo被执行。所以此条件下也可以认为两者效果相同。
我可以如此理解吗?
以及ELisp里有没有类似pass的东西?
可以这么理解,如果只关心 foo
是不是 nil
的话,它们是等价的。比如:
(when (if (foo)
t
(bar))
(do-something))
(when (or (foo)
(bar))
(do-something))
我认为从语义的角度来看两者并不同:
(or (foo) (bar)) 和 (or (bar) (foo)) 本质上等价,而短路求值只是一个实现层面的东西。
理论上我们写代码应该完全按照语义,而不是实现层面的东西,所以这两种写法哪种更好取决于语义。
nil本身就可以pass啊
还有个函数ignore,接受任意参数,忽略他们并返回nil
因为lisp所有东西都是表达式,换js py之类的不用短路运算就得三目了
所以我工作的时候就基本不会用短路……毕竟有别人要看。
但是自己写的代码就到处都是…
说白了还是想少打点字……
但是要返回值的话只能三元运算符了……
然而语义就是短路求值。
Eval args until one of them yields non-nil, then return that value.
The remaining args are not evalled at all.
If all args return nil, return nil.
短路求值几乎所有语言都有,大家都懂,又不是什么很难理解的东西。
今天写代码就用到了这个,读取文件做一些计算(如果出错就返回 0):
(or (ignore-errors ...) 0)
用 if
就很麻烦了。
其实“A and/or B"和“B and/or A"在大多数语言中都不是语义等价的。
但是它们逻辑上等价。
我觉得楼主的例子举错了,应该是这样
(if (foo)
(foo)
(bar))
这样就完全等价了。当然更好的写法是用let
。不过这种写法都不如or
了。
那本 《Writing GNU Emacs Extensions》里推荐这样写。
你这样的 (foo)
就求值了两次,当 (foo)
有副作用时行为就不等价了。
至少也得是 (let ((res (foo))) (if res res (bar)))
只是举例而已,都说了应该用let。你这样写当然是最好啦
这样写打字多 有没有更好的写法
我选择用 Haskell。
讲道理 Haskell 的 hlint 是提倡用 ||
(binary operator OR) 较于 if_else_then_
的。
完全是个人主观的问題我沒法给答案。