【问题标题】:Get two elements from a sequence each time每次从一个序列中获取两个元素
【发布时间】:2012-04-05 14:04:43
【问题描述】:

clojure 是否像普通的 lisp 一样具有强大的“循环”。

例如:

每次从一个序列中获取两个元素

普通的 Lisp:

(loop for (a b) on '(1 2 3 4) by #'cddr collect (cons a b))

如何在 Clojure 中做到这一点?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    通过利用for 和一些解构,您可以实现您的具体示例:

    (for [[a b] (partition 2 [1 2 3 4])](use-a-and-b a b))
    

    【讨论】:

    • 请注意for 不是循环结构,而是列表理解,产生惰性序列的结果。此外,与 Common LISP 相比,很难让它表现得非常出色。
    • @Marko - 你有具体的例子吗?
    • 不明白——具体是什么例子?
    • 我的观点不是具体的,而是笼统的。 Lisp 的loop 是一个执行控制结构,更类似于Clojure 中的doseqloop。 OP 的示例专门使用collect 来指定类似map 的操作,这只是使用loop 的一种方式。在 Clojure 中,您通常与 for 一起使用的东西,例如惰性序列、高阶函数、partition 生成的辅助向量等,在时间和空间上都是昂贵的。
    • @St3fan - 谢谢 - 我的评论应该是“表现不佳的例子”。如果没有特定的用例,挥手“表现不佳”或“难以让它表现得非常好”并不是那么有用。性能并非总是最重要的问题,clojure 在许多地方都以清洁和简单换取原始性能。那么“问题”是性能很容易量化,而清洁度/简单性则不是,因此评估权衡可能很困难。我更喜欢简单而不是效率,效率而不是性能,除非并且直到我真的知道我遇到了问题......
    【解决方案2】:

    cl-loop,类似于LOOP,还有clj-iterclj-iterate,它们都是基于Common Lisp的iterate looping construct

    【讨论】:

      【解决方案3】:

      Clojure 的多用途循环结构是for。它没有内置的 CL 的 loop 那么多功能(尤其是没有副作用的功能,因为 Clojure 鼓励功能纯度),因此您可能只需使用 loop 本身就可以完成的许多操作“围绕“for。例如,要将for 生成的元素相加,您可以在其前面放置一个apply +;要成对地遍历元素,您将(如 sw1nn 所示)在输入到 for 的输入序列上使用 partition 2

      【讨论】:

        【解决方案4】:

        我会用looprecur 和解构来做到这一点。

        例如,如果我想将每两个值组合在一起:

        (loop [[a b & rest] [1 2 3 4 5 6]
               result []]
          (if (empty? rest)
            (conj result [a b])
            (recur rest (conj result [a b]))))
        

        结果是:

        => [[1 2] [3 4] [5 6]]

        ab分别是序列的第一个和第二个元素,然后rest是剩下的。然后我们可以递归地遍历,直到rest 中没有任何剩余,我们就完成了。

        【讨论】:

        • 但这已经由(partition 2 [1 2 3 4 5 6]) 完成:((1 2) (3 4) (5 6))
        猜你喜欢
        • 1970-01-01
        • 2021-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-02
        • 2010-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多