Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Optimization Clojure是否具有短路逻辑?_Optimization_Clojure_Short Circuiting - Fatal编程技术网

Optimization Clojure是否具有短路逻辑?

Optimization Clojure是否具有短路逻辑?,optimization,clojure,short-circuiting,Optimization,Clojure,Short Circuiting,在许多语言中,如果你按照 if (foo() || bar() || foobar()) { /* do stuff */ } 并且foo()返回true,则不会计算bar()和foobar() 假设我有以下Clojure代码: (let [a (simple-function args) b (complex-function args) c (too-lazy-to-optimize-this-function args)] (or a b c)) 如果a的计

在许多语言中,如果你按照

if (foo() || bar() || foobar()) { /* do stuff */ }
并且foo()返回true,则不会计算bar()和foobar()

假设我有以下Clojure代码:

(let [a (simple-function args)
      b (complex-function args)
      c (too-lazy-to-optimize-this-function args)]
  (or a b c))
如果a的计算结果为true,那么b和c也会被计算,还是会被忽略


谢谢

当我输入完这个问题后,我意识到我可以查看“或”的文档

从文档中: 从左到右一次计算一个表达式。如果 返回逻辑真值,或返回该值而不返回 对任何其他表达式求值,否则返回 最后一个表达式的值。(或)返回nil。“

如有疑问,请咨询:



用法:

从左到右一次计算一个表达式。如果是表格 返回一个逻辑真值,或返回该值,但不返回 对任何其他表达式求值,否则返回 最后一个表达式的值。(或)返回零

(我的重点。)

显示它的行为方式也相同

if (foo() || bar() || foobar()) { /* do stuff */ }


由于您回答了自己的问题,请注意,尽管在示例b和c中,可能没有在(或b c)调用中计算let绑定,但在此之前会对let绑定进行计算,因此不会对太懒的函数调用进行优化。Clojure没有那么懒

需要明确的是:要有条件地计算函数调用,需要将计算它们的表达式放在
调用中,基本上:

(or (simple-function args)
    (complex-function args)
    (too-lazy-to-optimize-this-function args))

其他答案都很好,但如果有疑问,您可以在REPL上进行测试:

user=> (or true (do (println "hello") true))
true
user=> (or false (do (println "hello") true))
hello
true

是的,Clojure确实有短路评估

Clojure/other Lisps中一个有趣的特性是,还可以使用新的结构来扩展该语言,这些结构也可以提供短路评估。使用大多数其他语言中的函数无法做到这一点,因为在调用函数之前必须对函数的所有参数进行求值

以下是在Clojure中实现短路NAND功能的宏示例:

(defmacro nand 
  ([x] 
    `(not ~x))              ; NAND is equivalent to NOT for one argument
  ([x & xs] 
    `(let [nand# (not ~x)]
       (if nand# 
         true               ; short circuit if we can prove the nand is true
         (nand ~@xs)))))    ; continue with the other expressions otherwise

(nand true true)
=> false

(nand false (println "Expression with a side effect!"))
=> true

我之所以接受这一点,是因为它讨论了我不知道的gotcha。它不是gotcha,而是你必须理解所有的东西都是渴望的,除了惰性序列,以及在它们上工作的函数。“或”短路,因为它是一个宏,所以会扩展到。如果它是一个函数,它将计算它的参数。相反,它宏扩展为if,这是一种特殊形式和短路。
(or (simple-function args)
    (complex-function args)
    (too-lazy-to-optimize-this-function args))
user=> (or true (do (println "hello") true))
true
user=> (or false (do (println "hello") true))
hello
true
(defmacro nand 
  ([x] 
    `(not ~x))              ; NAND is equivalent to NOT for one argument
  ([x & xs] 
    `(let [nand# (not ~x)]
       (if nand# 
         true               ; short circuit if we can prove the nand is true
         (nand ~@xs)))))    ; continue with the other expressions otherwise

(nand true true)
=> false

(nand false (println "Expression with a side effect!"))
=> true