【问题标题】:Are Futures in Scala really functional?Scala 中的 Futures 真的有用吗?
【发布时间】:2015-02-19 21:32:43
【问题描述】:

我正在阅读此博客 post,声称 Futures 不是“功能性的”,因为它们只是 副作用 计算的包装。例如,它们包含 RPC 调用、HTTP 请求等。是否正确?

博文给出了以下示例:

def twoUsersFeed(a: UserHandle, b: UserHandle)
                (implicit ec: ExecutionContext): Future[Html] =
  for {
    feedA <- usersFeed(a)
    feedB <- usersFeed(b)
  } yield feedA ++ feedB

you lose the desired property: consistent results (the referential transparency). Also you lose the property of making as few requests as possible. It is difficult to use multi-valued requests and have composable code.

恐怕我不明白。您能解释一下在这种情况下我们是如何丢失consistent result 的吗?

【问题讨论】:

    标签: scala concurrency functional-programming future


    【解决方案1】:

    这篇博文未能正确区分 Future 本身和它的常用方式 IMO。你可以用Future 编写纯函数代码,如果你只写过Futures 调用纯函数;这样的代码将是引用透明的,并且在每一个遥远合理的意义上都是“功能性的”。

    事实是,Futures 让您对副作用的控制有限,如果您将它们与具有副作用的方法一起使用。如果您创建一个Futurewrapping webClient.get,那么创建该Future 将发送一个HTTP 调用。但这不是关于Future 的事实,这是关于webClient.get 的事实!

    这篇博文有一定的道理。通过例如,将表达您的计算与执行它完全分开Free monad,可以产生更高效和更可测试的代码。例如。您可以创建一种“查询语言”,在其中表达“获取 A 和 B 的所有共同朋友的个人资料照片”之类的操作,而无需实际运行它。这使得测试你的逻辑是否正确变得更容易(因为它很容易制作一个可以“运行”相同查询的测试实现 - 甚至只是直接检查“查询对象”),并且,正如我认为的博客文章试图建议,意味着你可以例如组合多个请求以获取相同的配置文件。 (这甚至不是纯粹的函数式编程问题——一些 OO 书籍有“命令模式”的想法——尽管像 for/yield 语法这样的 IME 函数式编程工具使以这种方式工作更容易) .然而,如果您只有一个 fetchProfile 方法,该方法在运行时会立即触发 HTTP 请求,那么如果您的代码逻辑两次请求相同的配置文件,则无法避免两次获取相同的配置文件。

    但这并不是关于 Future 本身的问题,而且 IMO 这篇博文更令人困惑而不是有用。

    【讨论】:

    • 谢谢。现在很清楚了。我喜欢分离表达计算和执行的想法。会看Free monad
    猜你喜欢
    • 2015-12-30
    • 2013-02-09
    • 2021-11-21
    • 2019-10-13
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    相关资源
    最近更新 更多