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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.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
为什么Clojure习惯用法更喜欢返回nil而不是像Scheme一样的空列表?_Clojure_Idioms - Fatal编程技术网

为什么Clojure习惯用法更喜欢返回nil而不是像Scheme一样的空列表?

为什么Clojure习惯用法更喜欢返回nil而不是像Scheme一样的空列表?,clojure,idioms,Clojure,Idioms,从中,有人说Clojure习惯用法更喜欢返回nil,而不是Scheme中的空列表。为什么呢 像 而不是 (if (empty? lat) '() ...) 既然我写了评论,我会写一个答案。(skuro的回答提供了所有信息,但可能太多) 首先,我认为更重要的事情应该放在第一位 seq正是每个人大部分时间都在使用的东西,但是empty?对它来说很好(不是(seq lat)) 在Clojure中,“()是true,因此通常情况下,如果序列完成,您希望返回false 如果您的数据库中只

从中,有人说Clojure习惯用法更喜欢返回nil,而不是Scheme中的空列表。为什么呢

而不是

  (if (empty? lat)  
    '() ...)

既然我写了评论,我会写一个答案。(skuro的回答提供了所有信息,但可能太多)

  • 首先,我认为更重要的事情应该放在第一位
  • seq
    正是每个人大部分时间都在使用的东西,但是
    empty?
    对它来说很好
    (不是(seq lat))
  • 在Clojure中,“()是true,因此通常情况下,如果序列完成,您希望返回false
  • 如果您的数据库中只有一个importend分支,而另一个分支返回false/'()或类似的值,那么为什么要写下该分支<代码>当只有一个分支时,如果你想产生副作用,这是特别好的。您不必使用
    do
  • 请参见此示例:

    (如属虚假) '() (do(println 1) (println 2) (println 3)))

    你可以写

    (如果为true (打印1) (println 2) (第3页)

    没什么不同,但我认为读起来更好


    附言


    并不是说有函数称为
    如果不是
    如果不是
    ,它们通常比
    (如果不是真的)
    更好。
    我可以想到几个原因:

    • 逻辑区别。在Clojure中,nil表示无价值/无价值。而“()”空列表是一个值-它恰好是一个空列表的值。从概念上和逻辑上区分这两者通常很有用

    • 适合JVM-JVM对象模型支持空引用。相当多的Java API返回空表示“无”或“未找到值”。因此,为了确保易于JVM互操作性,Clojure以类似方式使用nil是有意义的

    • 惰性-这里的逻辑相当复杂,但我的理解是,使用nil表示“no list”更适合Clojure。由于Clojure在默认情况下是一种惰性函数式编程语言,因此将此用法作为标准用法是有意义的。有关更多说明,请参阅

    • “Falsiness”-在编写检查集合的条件代码时,可以方便地使用nil表示“nothing”,也可以表示“false”-因此您可以编写类似
      (if(some map:some key)…)
      的代码来测试hashmap是否包含给定键的值

    • 性能-测试nil比检查列表是否为空更有效……因此,将此习惯用法作为标准可以产生更高性能的习惯用法代码

    请注意,Clojure中仍有一些函数返回空列表。例如rest:

    (rest [1])
    => ()
    

    这详细说明了为什么会这样……

    还请注意,集合类型和nil的并集形成了一个幺半群,将幺半群加上,nil将幺半群为零。因此,nil将空列表语义保持在串联状态下,同时还表示一个假值或“缺失”值

    Python是另一种语言,其中公共幺半群标识表示假值:0、空列表、空元组

    由于空集合在布尔上下文中的行为类似于
    true
    ,因此您需要一种习惯用法来测试集合中是否有任何内容需要处理。谢天谢地,Clojure提供了这样一种技术:

    (seq [1 2 3])
    ;=> (1 2 3)
    
    (seq [])
    ;=> nil
    

    在其他Lisp中,如Common Lisp,空列表用于表示
    nil
    。这称为nil双关,只有在空列表为false时才可行。返回
    nil
    这是clojure重新引入nil双关的方法。

    FWIW,如果返回
    ()
    作为一个文本,调用方可以快速测试它,因为它的类将是
    clojure.lang.PersistentList$EmptyList
    。检查它肯定比测试
    empty?
    seq
    要快,尽管可能仍然比检查
    nil
    要慢一点。我想应该有助于解决这个问题。一个错误lue当然比truthy更适合返回。其他Lisp(如Common Lisp)将空列表视为虚假。Clojure没有按照skuro链接中的答案进行操作。如果
    (if)(seq some list)…
    始终以第一种形式执行。Scheme通常不会返回空列表,Scheme过程通常会返回
    #f
    或根本不返回值。空列表通常作为递归过程的基本情况返回。您知道如果有加法,任何n+0=n?,如果有逻辑or,任何n或true=n?,如果在Clojure中有列表连接,any(concat n nil)=n?因此,在操作中存在这种“缺失事物”的模式。Clojure使用nil表示许多情况下的“缺失”概念,因此您可以使常用算法(如树漫游器)更通用、更清晰。
    (seq [1 2 3])
    ;=> (1 2 3)
    
    (seq [])
    ;=> nil