代码之家  ›  专栏  ›  技术社区  ›  Atty

为什么Clojure中的list*只对尾部位置的向量起作用?

  •  1
  • Atty  · 技术社区  · 6 年前

    我是个新手。我想到处玩 repl 我把下面的作为输出。我不太明白为什么他们每个人的行为都如此不同

    (def a (list 1 2 3))  =>#'test.core/a
    
    (list* 4 5 a)          =>(4 5 1 2 3)
    
    (list* a 4 5)         =>IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:542)
    

    为什么上面两个语句在上面两个语句中的行为相同?

    (list* 4 5 [1 2 3])     =>(4 5 1 2 3)
    
    (list* 4 5 [a])       =>(4 5 (1 2 3))
    
    (list* 4 5 (1 2))     =>ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn  test.core/eval3837 (form-init633779145118520639.clj:1)
    

    2 回复  |  直到 6 年前
        1
  •  2
  •   Alex Stoddard    6 年前

    请参阅列表*的doc字符串:

    创建一个新的seq,其中包含在rest前面的项,最后一个 其中的一个将被视为一个序列。

    注意seq不是一个列表,但是列表和向量以及其他东西可以被看作序列。当repl的输出看起来像一个列表时,还会有一个seq—它是在parens中打印的。

    所以在第一种情况下,最后一个参数是一个文字向量,它被当作一个序列,得到一个不受尊重的序列。

    在第二种情况下,将列表“a”作为一个文本向量中的单个元素,因此该向量被视为一个序列,但内部列表不是,返回的序列有三个元素长:4、5和列表a。

    在最后一种情况下,您会发现lisps中的函数调用语法与list语法非常相似。(12)正在尝试调用数字1,如同它在函数中一样(带参数2)。文字数字不能解释为函数。

    如果要使用列表文字而不是函数调用,则必须引用它:

    (list* 4 5 '(1 2)) => (4 5 1 2)
    
        2
  •  4
  •   Carcigenicate    6 年前

    definition 和docstring,这是有意义的。

    医生说:

    “创建一个新的seq,其中包含附加到其余项的项, ."

    在第一个块中,最后一个表达式失败,因为5是最后一个参数,但不是序列。

    (list* 4 5 [1 2 3]) 因为同样的原因 (list* 4 5 a) 作品。正如预期的那样,最后一个参数是一个序列。只是 cons 在定义中可以看到最后一个参数。

    (list* 4 5 [a]) a 在另一个收藏中。它只会添加到外部集合中,而不会影响内部集合。

    失败 (list* 4 5 (1 2)) (...) 它将尝试对其求值,并期望列表中的第一个元素是可调用的。但是1不可调用,因此出错。您需要引用它,将其视为列表文字,而不是要计算的代码。