如何抽象一个列表以便在 Clojure 中的其他函数中操作它?

Log*_*air 1 functional-programming clojure

我对函数式语言非常陌生,我正在尝试在 Clojure 中实现一个简单的附加函数。我的代码:

(defn append
  [lizt1 lizt2]
  (cond
    (empty? lizt1) lizt2
    :else (def sq (cons (first sq lizt1) (append (rest sq lizt1) lizt2)))))

(let [x (quote (1 2 3))
      y (quote (4 5 6))]
  (append (x y))) ) 
Run Code Online (Sandbox Code Playgroud)

我收到了

  clojure.lang.PersistentList cannot be cast to clojure.lang.IFn 
Run Code Online (Sandbox Code Playgroud)

异常,所以我假设我尝试传递给函数的列表不是兼容类型(就像我要执行列表函数并尝试传递它一样)。我认为引用该列表将使其可以通过接口函数访问。有人可以帮助我概念化如何抽象列表以便在单独的函数中操作其数据吗?

Mar*_*ůda 9

错误的根源是这个调用:

(append(x y))
Run Code Online (Sandbox Code Playgroud)

该表达式不append使用参数xand进行调用y,而是x使用参数进行调用y,并且此调用的结果用作 的参数append

但是x列表和列表不能用作函数 - 这就是 的含义clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

在 Clojure 中,括号的位置非常重要,“call appendwith xand y”的正确语法是:

(append x y)
Run Code Online (Sandbox Code Playgroud)

但还有更多需要修复的地方:

  • quote通常缩写为'
'(1 2 3)
=> (1 2 3)
Run Code Online (Sandbox Code Playgroud)

但我建议你使用向量,如下所示:

[1 2 3]
=> [1 2 3]
Run Code Online (Sandbox Code Playgroud)
  • 您不必let在这里使用两个嵌套,一个let可以有多个绑定:
(let [x [1 2 3]
      y [4 5 6]]
  ...)
Run Code Online (Sandbox Code Playgroud)
  • Cond只有两个分支是if.
  • 不要使用definside defn-def创建一个全局变量。当您确实需要在函数内创建一些变量时,请使用let.

您正在寻找的解决方案如下所示:

(defn append [col1 col2]
  (if (empty? col1) 
    col2
    (cons (first col1)
          (append (rest col1) col2))))
                    
(let [x [1 2 3]
      y [4 5 6]]
  (append x y))
=> (1 2 3 4 5 6)
Run Code Online (Sandbox Code Playgroud)

(还有一个更惯用的版本seq,但empty?也可以使用。)

请注意,有一个函数concat可以执行完全相同的操作。