【问题标题】:Why filter stuck in nrepl?为什么过滤器卡在 nrepl 中?
【发布时间】:2013-04-10 06:26:39
【问题描述】:

为什么最后一个表达式永远卡在 nrepl 中(我猜它永远不会停止)。 我必须 Ctrl+c Ctrl+c 才能停止它。

【问题讨论】:

    标签: clojure nrepl


    【解决方案1】:

    因为您正在尝试评估无限序列(通过将其打印到 REPL)。

    例如的结果(filter #(> % 100) (iterate #(+ % 17) 0)) 可以打印到 REPL,因为 REPL 将打印结果序列的第一个 x 元素,然后是 ...,其中 x 是您可以使用 (set! *print-length* x) 设置的值。

    但尝试评估(filter #(< % 100) (iterate #(+ % 17) 0)) 将永远运行,因为只有 6 个可能的元素。


    查看*print-length* 文档:

    ;; Oops! Don't this!!!
    user=> (iterate inc 0)
    ;; Frantically doing C-c C-c :-P
    ; Evaluation aborted.
    
    user=> (set! *print-length* 10)
    10
    
    ;; Now it's perfectly fine. Yay!
    user=> (iterate inc 0)
    (0 1 2 3 4 5 6 7 8 9 ...)
    

    您可能想要使用take-while 而不是filter,因为您使用iterate 创建的序列已经排序。

    user=> (take-while #(< % 100) (iterate #(+ % 17) 0))
    (0 17 34 51 68 85)
    

    【讨论】:

    • 我在问为什么有限的结果不会被打印出来。仅仅因为它的长度小于print-length?很奇怪吗?
    • 这里没有有限序列,迭代是无限的,对无限序列运行过滤器会导致无限序列。
    • 仅仅因为它的长度小于 print-length? REPL 只是试图获取第一个 x 元素。 REPL 无法知道获取这些元素需要多少时间,或者是否有可能。此外,您的序列不是有限的。
    • 那么,如果我想生成小于例如 100 但为 5 的倍数的数字怎么办?这是我最初的目标。
    • @easterbunny 您可以使用take-while 代替过滤器。查看我的更新。
    【解决方案2】:

    如上面的表达式response中打印的序列不是完整的结果(检查序列末尾的...),这表明nrepl在返回一个序列的响应时take具体的项目数来自序列并用 ... 打印它们以指示序列中还有更多。在你的最后一种情况下,“少于 100 个数字”不会产生 nrepl 打印所需的最小项目数,因此 nrepl 继续等待序列中的更多项目(这是一个无限序列,因为迭代)

    【讨论】:

      【解决方案3】:

      您的序列中只有 3 个数字小于 100。但是,由于它是“无限”的,filter 必须查看“无限”个元素来确定第四个元素不存在。

      由于您的示例 iterate 构造生成一个递增序列,如果您想将结果限制为小于 100 个的元素,您可以使用 take-while。例如:

      (take-while #(< % 100) (iterate #(+ % 17) 0))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-06
        • 1970-01-01
        • 2021-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多