【问题标题】:Is List-Comprehension any better than List-Abstractions?List-Comprehension 是否比 List-Abstractions 更好?
【发布时间】:2023-04-02 10:19:02
【问题描述】:

为什么人们更喜欢像
(for [x '(1 2 3)] (* 2 x)) 这样的列表推导而不是(map #(* %1 2) '(1 2 3))

这种编程有什么好处吗?
1. 是否更具可读性?
2. 在某些情况下会更快吗? 3. 对某些类型的操作和数据结构更好吗?

【问题讨论】:

    标签: functional-programming clojure list-comprehension


    【解决方案1】:

    对于您给出的示例,没有任何好处;但一般来说,for 在您连接两个(或更多)序列时很有用,或者当您需要进行一些过滤时 - for:let:when 通常比一连串更具可读性嵌套mapfilter

    【讨论】:

      【解决方案2】:

      列表推导仅仅是 超出标准的“语法糖” 功能程序,但它们给出了一个 直观阅读常用操作 在列表中。 ——盖伊·拉帕尔梅

      他们唯一的目的是提高可读性。不要期望通过使用它们来显着提高性能。

      This 论文对在类似 Lisp 的语言中实现列表推导提供了一些见解。

      【讨论】:

        【解决方案3】:

        一些一般的想法

        首先,列表推导式只是语法糖,所以除了可读性之外应该没有本质上的区别。

        但请注意,列表推导实际上将至少三个高阶函数统一,即mapfilterconcatMap 合并为一个语法。因此,在需要这些复杂组合的重要情况下,语法可以具有很大的可读性优势。

        除此之外,还可以方便地使用值绑定来存储结果并使事情更加清晰:

        [ (x, y) | x <- [1..10],
                   y <- [1..10], 
                   let dist = (x - 5)² + (y - 5)²,
                   dist < 10² ]
        

        但无论如何,列表推导可以比仅处理列表更通用。基本上,他们可以使用统一且方便的语法处理任何Monad。例如,F# 甚至将其扩展到控制任意程序流。

        其次,列表推导比通常的高阶函数更抽象,可能实际上更快,因为编译器可以利用优化法则,否则将由程序员决定考虑。

        [ x + 1 | x <- numbers, even x ]
        

        直接的翻译应该是

        map (\x -> x + 1) (filter even x)
        

        列表被迭代两次,产生一个毫无价值的中间结果。

        但是,编译器可以识别和优化上述模式,并生成直接优化的filterMap 版本。

        【讨论】:

          【解决方案4】:

          列表推导式用于需要以更复杂的方式遍历序列的情况。在您的示例中,它们是相同的,因此我会推荐地图,因为它更易于阅读。

          map cant 因为 do 而变得丑陋,例如:

          (for [x '(1 2 3) y '(3 2 1)] (* 2 x y))
          

          【讨论】:

          • 单个map 不能,但mapcat 可以。通常,总是可以用mapmapcatfiltertake-while 的某种组合来替换列表推导式。只是对于更复杂的情况,结果可能很难阅读。
          • 不,尽管它与上面的 for 不一样。我相信您可以删除 (list 并仅使用 map 来获得与此相同的效果。示例中的代码遍历 x 和 y 的所有组合。就像 java 中的 2 个嵌套 for 循环。
          • 你是对的。我们需要两张地图来做那些嵌套循环的事情。那么它只是为了让你的代码更具可读性吗?列表推导扩展到什么?
          【解决方案5】:

          我知道这是一个 Clojure 问题,但 Martin Odersky 等人的《Programming in Scala》一书中很好地讨论了 for 理解如何映射到 mapfilter 函数。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-05-13
            • 2020-11-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多