惰性序列在消耗堆栈的递归调用中不起作用

Lazy sequence doesn't work in stack-consuming recursive calls

我找到了一个简单(但效率低下)的解决方案,在 Clojure 中基本上可以这样写:

(defn make-someof [data]
  (fn sumf
    ([x n ds]
     (if (= n 1)
       (if (some #{x} ds) 1 0)
       (reduce + (for [m (filter #(< % n) ds)]
                   (sumf (- x m) (dec n) (disj ds m))))))
    ([x n] (sumf x n data))))

可以这样称呼:

((make-someof #{1 2 3 4 5 6}) 7 2)

但事实证明,make-sumof 函数的 reduce 部分中的表单仅被评估一次。 (即其中有 6 个值的 filter 表单仅针对它的第一个值进行迭代!)

我也尝试在 for 形式上使用 doall,从而强制计算它,但是递归调用到达第一个形式的那一刻(当条件 (= n 1) 成立时)结果表达式(在本例中为 (if (some #{x} ds) 1 0) 形式的 1)作为整个调用链的结果返回。

这对我来说没有意义。
也许我犯了一个大错误或者这是 Clojure 中的错误?

注意:此函数应该计算数字 7 可以写成来自特定不同数字的另外 2 个数字之和的方式数(在本例中 #{1 2 3 4 5 6})。

我很想弄清楚这里发生了什么,因为这个函数可以用 loop 形式编写。

您的过滤谓词 #(< % n) 旨在从可用加数集中删除大于剩余目标总和的数字,而是测试小于加数 [=11] 的加数=].请尝试使用 #(< % x)