【问题标题】:Can "list comprehension" be considered as "functional programming"?“列表理解”可以被视为“函数式编程”吗?
【发布时间】:2014-05-28 10:00:13
【问题描述】:

Scala 代码:

for {
   user <- users
   name <- user.names
   letter <- name.letters
} yield letter

我们可以将这种“列表理解”代码视为“函数式编程”风格吗?因为它们会被转换为mapflatMap 函数?

【问题讨论】:

    标签: scala functional-programming list-comprehension


    【解决方案1】:

    是的,它绝对是一种函数式技术,尤其是假设所有这些成员都是字段或纯函数。它只是 0 个或多个 flatMaps 后跟 1 个 map 的语法糖(if 子句转换为 withFilter)。

    末尾没有yield,它的行为更像是命令式for,转换为1个或多个foreachs; foreach 通常用于执行语句的副作用。

    This article 更详细地描述了语法,this excellent answer 更深入地讨论了一些单子理论,this article 明确地描述了实际的规则转换。

    【讨论】:

    • 其实foreach 不是命令式的对应物。 for 理解可以翻译成foreach,它们只是为了更清晰的语法糖。
    • @goral 我原来的答案肯定有问题。我忘记了非收益for 仍然称为for,而不是foreach。但是foreachCollection 方法,没有实现问题中描述的for...yield 构造,flatMap/map 做。
    【解决方案2】:

    列表理解结构在函数式编程语言中很常见,但它与函数式编程没有区别。如果您考虑一下 Python、PHP(从 5.5 版开始)和 Javascript 的下一个版本(ES6)也有类似的结构,但这并不意味着它们是功能性的。

    在 scala 的情况下,您的示例确实可以转换为 map 和 flatMap 应用程序,但恕我直言,这还不足以说明它是功能性的。考虑案例:

    for {
      i <- 1 until 10
    } println(i)
    

    这仍然是一种理解,但它实际上与任何命令式语言一样会产生副作用(这个循环实际上转换为 foreach 调用)。

    在我看来,最重要的是,函数式编程与其说是关于结构,不如说是关于风格:对于一段 FP 风格的代码来说,真正重要的是没有副作用(或者,在许多情况下,说实话,副作用何时发生)。

    如果你愿意,即使在 Java 7 中也可以使用 FP:使用匿名类作为闭包,将所有内容标记为 final,避免任何可变状态并将副作用隔离到特殊构造中,然后就完成了。它会非常冗长并且可能很难看,因为该语言不支持有助于在实践中使这种风格变得更好的抽象类型,但它仍然是函数式的。

    【讨论】:

      【解决方案3】:

      我们可以将这种“列表理解”代码视为“函数式编程”风格吗?

      具有命令式/生成器语法的一元列表推导是一种相对较新的语法和语义创新。

      最初的列表推导(例如NPLMiranda)以set comprehensions 为蓝本,显然是一种声明性构造,尽管它被转换为嵌套函数。

      Haskell 的列表推导功能类似。

      如果我们将 monad 视为一种函数式构造,那么 Monad 推导式(编译为 monadic 守卫和绑定)肯定应该被视为函数式。

      【讨论】:

        猜你喜欢
        • 2019-07-04
        • 2012-06-13
        • 2023-01-27
        • 1970-01-01
        • 2021-10-06
        • 2018-10-12
        • 1970-01-01
        • 1970-01-01
        • 2014-11-22
        相关资源
        最近更新 更多