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
Clojure 将空列表传递给函数以收集结果_Clojure - Fatal编程技术网

Clojure 将空列表传递给函数以收集结果

Clojure 将空列表传递给函数以收集结果,clojure,Clojure,我一直找不到任何关于我试图理解的东西的理论上的Clojure的例子,并希望得到一些关于它的意见 传统上,当我在命令式语言中使用递归时,我经常将空列表传递给递归函数,以便通过堆栈向下收集一些计算结果 作为Java中的一个小例子: public List<Integer> results = new ArrayList<>(); private List<Integer> add(List<Integer> list, int count){

我一直找不到任何关于我试图理解的东西的理论上的Clojure的例子,并希望得到一些关于它的意见

传统上,当我在命令式语言中使用递归时,我经常将空列表传递给递归函数,以便通过堆栈向下收集一些计算结果

作为Java中的一个小例子:

public List<Integer> results = new ArrayList<>();

private List<Integer> add(List<Integer> list, int count){
    if(count > 10){
        return list;
    }

    count = count + 1;
    list.add(count);

    return add(list, count);
}
将生成值0到10的列表

这是Clojure的惯用语吗

(defn t [list i]
    (conj list i)
    (if (<= i 10)
        (recur list (inc i))))

(t '() 0)
我是否得到以下错误:

clojure.lang.Compiler$CompilerException:java.lang.ClassCastException:java.lang.Long(在模块:java.base中)不能强制转换为clojure.lang.IFn

这是Clojure的惯用语吗

(defn t [list i]
    (conj list i)
    (if (<= i 10)
        (recur list (inc i))))

(t '() 0)
不是

在Clojure。因此,一旦调用传递列表的函数,该函数就无法修改它。所以,它不仅不地道,而且不可能

相反,在Clojure中实现所需功能的惯用方法是调用递归函数来构建一个较小的列表,并将其追加到其中

(defn my-range [n]
  (if (< n 0)
    []       ; empty list
    (conj
     (my-range (dec n)) ; recursive call to build smaller list
     n)))     
(定义我的范围[n]
(如果(
话虽如此,您提供的Java代码片段也不是很好;总的来说,这里有一个很好的惯例:

  • 如果该方法具有void返回类型,则可能会产生副作用,并且可能会修改其中一个参数
  • 如果该方法具有返回类型,那么您可能希望不修改参数

给该方法一个返回类型,同时修改一个参数,会使代码变得混乱。代码的用户无法知道是使用返回还是提供自己要修改的列表。

您当然可以传入一个空列表作为结果的起点。这里应用的clojure习惯用法是函数调用

(conj list i)
返回一个添加了i的新列表,但它不会改变列表,因此在t函数中,该行不会产生任何结果。要使用该函数调用的结果,应将其作为参数传递给recur,类似于(inc i)

第二点要注意的是if语句中没有其他条件,因此一旦i的值大于10,if语句将返回nil

(defn t1 [list i]
  (if (<= i 10)
    (recur (conj list i) (inc i))
    list))
(定义t1[列表一]

(如果(注意,
conj
对于向量和列表类型的行为不同。对于向量,它会在末尾附加一个元素。对于列表,它会将元素放在其头部的前面:

user=> (conj [1 2 3] 4)
[1 2 3 4]
user=> (conj '(1 2 3) 4)
(4 1 2 3)
因此,如果任何人传递的是向量而不是列表,他或她将面临不可预测的行为。请注意,在Clojure中,向量比列表更常见(与Scheme或common list不同)

concat
功能适用于两种类型:

user=> (concat [1 2 3] [4])
(1 2 3 4)
user=> (concat '(1 2 3) [4])
(1 2 3 4)

然后,调用
(conj list i)
将返回一个新的列表,而不更改前一个列表。此调用应放在其他函数调用中,例如,在
recur
let
内。否则,您将徒劳地执行。

conj不会发生变异,因此您需要显式地传递其返回值。即
(defn[list i](如果(
user=> (concat [1 2 3] [4])
(1 2 3 4)
user=> (concat '(1 2 3) [4])
(1 2 3 4)