【问题标题】:Beginner Clojurist Lazy Sequence error: Don't know how to create ISeq from: java.lang.Long初学者 Clojurist 惰性序列错误:不知道如何从:java.lang.Long 创建 ISeq
【发布时间】:2016-05-04 19:16:12
【问题描述】:

我是 Clojure 和 Lisp 的新手,但到目前为止我很喜欢它。我目前正在尝试了解惰性序列和 Clojure 定义无限序列的能力。我有以下代码:

(defn geometric
  ([] geometric 1)
  ([n] (cons n (lazy-seq (geometric (* n 1/2))))))

如果我跑:

(geometric)

在我的 REPL 中,它按预期返回 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)

为什么会出现此错误?如果我理解正确的话,应该能够将 n 用于惰性序列,并且 take 应该返回序列的前十个值,递归评估。

【问题讨论】:

    标签: clojure lisp


    【解决方案1】:

    我最喜欢的函数之一:iterate 接受一个函数 f 和一个值 x 返回 x, (f x), (f (f x), (f (f (f x))) 等。

    这是一个具有相同功能的优雅实现:

    (defn geometric []
      (iterate #(/ % 2) 1))
    

    不是直接回答您的问题,但希望能提供信息!

    【讨论】:

      【解决方案2】:

      您的代码中有一个小错字:

      (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),因为它会尝试评估无限序列。

      【讨论】:

        【解决方案3】:

        你的问题在这里:

        ([] geometric 1)
        

        这个表达式意味着,如果 geometric 不带参数被调用,会发生两件事:

        1. 将评估符号 geometric,从而生成 geometric 函数。
        2. 将返回号码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)
        

        【讨论】:

          【解决方案4】:

          (geometric) 计算结果为数字 1,而不是序列。 (take 10 1) 给出的错误与您现在看到的相同。

          您应该尝试运行(take 10 (geometric 1)),因为(geometric 1) 将生成一个序列,该序列可以提供给take 的第二个参数。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-27
            • 2020-08-18
            • 1970-01-01
            • 2012-08-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多