Beginner Clojurist Lazy Sequence error: Don't know how to create ISeq from: java.lang.Long
Beginner Clojurist Lazy Sequence error: Don't know how to create ISeq from: java.lang.Long
我是 Clojure 和 Lisp 的新手,但到目前为止很喜欢。我目前正在尝试了解 lazy-seq 和 Clojure 定义无限序列的能力。我有以下代码:
(defn geometric
([] geometric 1)
([n] (cons n (lazy-seq (geometric (* n 1/2))))))
如果我运行:
(geometric)
在我的 REPL 中,它 returns 1,正如预期的那样。但是,如果我 运行,
(take 10 (geometric))
我收到以下错误:
IllegalArgumentException Don't know how to create ISeq from:
java.lang.Long clojure.lang.RT.seqFrom
我期望得到的是:
(1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256 1/512)
为什么会出现此错误?如果我理解正确,应该能够对惰性序列进行 cons n 处理,并且应该 return 序列的前十个值,递归计算。
您的代码中有一个小错字:
(defn geometric
([] (geometric 1)) ;; notice the added parens around geometric 1
([n] (cons n (lazy-seq (geometric (* n 1/2))))))
没有这个修复 (geometric 1)
是有效的,因为实现是评估被丢弃的表达式 geometric
(只是一个函数值),然后 1
表达式被评估并作为函数结果(它是这个 arity 函数体中的最后一个表达式)。
现在它按预期工作了:
(take 1 (geometric))
;; => (1)
(take 5 (geometric))
;; => (defn geometric
([] geometric 1)
([n] (cons n (lazy-seq (geometric (* n 1/2))))))
请注意,您不能在 REPL 中安全地调用 (geometric)
,因为它会尝试计算无限序列。
(geometric)
的计算结果为数字 1,而不是序列。 (take 10 1)
给出与您现在看到的相同的错误。
你应该尝试 运行 (take 10 (geometric 1))
,因为 (geometric 1)
会产生一个序列,可以提供给 take
的第二个参数。
你的问题在这里:
([] geometric 1)
这个表达式意味着,如果不带参数调用 geometric
,将发生两件事:
- 将计算符号
geometric
,这将导致 geometric
函数。
- 将返回号码
1
。
你的意思可能是这样的:
([] (geometric 1))
这意味着调用(geometric)
等同于调用(geometric 1)
。您的示例现在将按预期工作:
(take 10 (geometric))
;=> (1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256 1/512)
我最喜欢的函数之一:iterate
接受函数 f
和值 x
返回 x, (f x), (f (f x), (f (f (f x)))
等
这是一个具有相同功能的优雅实现:
(defn geometric []
(iterate #(/ % 2) 1))
不是对您问题的直接回答,但希望能提供信息!
我是 Clojure 和 Lisp 的新手,但到目前为止很喜欢。我目前正在尝试了解 lazy-seq 和 Clojure 定义无限序列的能力。我有以下代码:
(defn geometric
([] geometric 1)
([n] (cons n (lazy-seq (geometric (* n 1/2))))))
如果我运行:
(geometric)
在我的 REPL 中,它 returns 1,正如预期的那样。但是,如果我 运行,
(take 10 (geometric))
我收到以下错误:
IllegalArgumentException Don't know how to create ISeq from:
java.lang.Long clojure.lang.RT.seqFrom
我期望得到的是:
(1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256 1/512)
为什么会出现此错误?如果我理解正确,应该能够对惰性序列进行 cons n 处理,并且应该 return 序列的前十个值,递归计算。
您的代码中有一个小错字:
(defn geometric
([] (geometric 1)) ;; notice the added parens around geometric 1
([n] (cons n (lazy-seq (geometric (* n 1/2))))))
没有这个修复 (geometric 1)
是有效的,因为实现是评估被丢弃的表达式 geometric
(只是一个函数值),然后 1
表达式被评估并作为函数结果(它是这个 arity 函数体中的最后一个表达式)。
现在它按预期工作了:
(take 1 (geometric))
;; => (1)
(take 5 (geometric))
;; => (defn geometric
([] geometric 1)
([n] (cons n (lazy-seq (geometric (* n 1/2))))))
请注意,您不能在 REPL 中安全地调用 (geometric)
,因为它会尝试计算无限序列。
(geometric)
的计算结果为数字 1,而不是序列。 (take 10 1)
给出与您现在看到的相同的错误。
你应该尝试 运行 (take 10 (geometric 1))
,因为 (geometric 1)
会产生一个序列,可以提供给 take
的第二个参数。
你的问题在这里:
([] geometric 1)
这个表达式意味着,如果不带参数调用 geometric
,将发生两件事:
- 将计算符号
geometric
,这将导致geometric
函数。 - 将返回号码
1
。
你的意思可能是这样的:
([] (geometric 1))
这意味着调用(geometric)
等同于调用(geometric 1)
。您的示例现在将按预期工作:
(take 10 (geometric))
;=> (1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256 1/512)
我最喜欢的函数之一:iterate
接受函数 f
和值 x
返回 x, (f x), (f (f x), (f (f (f x)))
等
这是一个具有相同功能的优雅实现:
(defn geometric []
(iterate #(/ % 2) 1))
不是对您问题的直接回答,但希望能提供信息!