【问题标题】:Java-Optional versus C++-optionalJava 可选与 C++ 可选
【发布时间】:2019-11-03 17:45:59
【问题描述】:

我是否正确地假设 Java-Optional 与 C++17-optional 没有太多关系?

我知道 Java Optional 主要来自 Stream-API,例如:

Optional<Integer> op  = Optional.empty(); 
op.stream().forEach(System.out::println); 

我知道它也可以用作返回值(与其说是参数)。但是关于这种用法,这不适用于C++-optional,对吧?

还是又是“Monads”,理解后没人能解释的东西? C++-optional 实际上是否与 Monads 有任何关系,Java-Streams 也是如此,因此 C++--optional 是否与 Java-Optional 相当?那么,有什么可比的例子呢?

【问题讨论】:

  • C++ 不是 Java。不要假设您对一种语言的了解任何内容都适用于另一种语言。
  • 如果您正在移植代码,我建议使用不同的路径:移植行为。理解 Java 代码所描述的行为并重新实现 C++ 中的行为 1:1 的代码翻译往往会得到次优结果,假设结果完全有用。

标签: java c++ java-stream monads optional


【解决方案1】:

Java 和 C++(以及许多其他编程语言)中的可选项用于类似的目的 - 表示可能存在或不存在的值。

Java 中的可选项不仅用于流,还可以(并且应该)以自己的方式使用。话虽这么说,在 Java 中,选项应该仅用作可能返回值或不返回值的方法的返回类型。通过返回 null 值可以实现相同的目的,但是这样更容易忘记检查返回的值。但是 Java 中的可选项不应该只是替换实际上可能不存在的每个对象(例如 Haskell 中的 Maybe)。

我不是 C++ 专家,但看起来 C++ 的 optional 具有大致相同的目的(如果我错了,请纠正我)。

我不会在这里解释什么是 monad,但是这个概念很简单,我真的不知道为什么这么多人害怕它们。如果您阅读过有关 monad 的任何内容,您就会知道它们基本上有 2 个操作:创建一个 monadic 值,然后绑定它(或对其进行平面映射)。

在 Java 中,Optional.of 创建一个可选值,而Optional.flatMap,好吧,平面映射它。但是这些操作并没有完全遵守 monadic 法则,所以纯粹主义者声称 Java 中的可选项并不是 真正的 monads。

在C++中,你可以使用构造函数或者make_optional函数来创建一个可选项,这样你就有了创建的操作。但我在标准库中找不到bindflat_map 函数。如果您愿意,您可以自己编写一个 - 如果该函数遵守 monad 法则,则可选项将成为 monad。

【讨论】:

  • flatMap+bind 缺失,没有 monad。好的,谢谢.. Haskells Maybe 是需要的,因为没有 null。 “纯粹主义者声称Optional 不是真的 monads”?真的吗?如果像 lambdas 的元组/三元组这样简单的东西是否是 monad 值得商榷,那么 monad 怎么能“不值得害怕”;-)
  • @towi monads 的概念本身并不难。但是,如果您深入了解技术细节,例如单子定律和基础数学,它可能很快就会变得非常困难。但是,大多数人不需要了解底层概念即可使用 monad 并在更高层次上理解其概念。
【解决方案2】:

我是否正确地假设 Java-Optional 与 C++17-optional 没有太大关系?

它们的相似之处在于它们模拟了相同的概念 - 一个可以不存在的值,但它们的接口非常不同。我对 C++ 不是很了解,但是看看 this page,我可以看到 C++ 的 std::optional 比 Java 的 Optional 少了很多功能

还是又是“Monads”,理解后没人能解释的东西?

准点! Java 的Optional 本质上是一个monad。通过拥有Optional.ofOptional.flatMap 方法,Java 的Optional 变成了一个monad。 C++ 可选缺少相应的flatMap 方法,这导致它不是一个monad :(

IMO,std::optional 没有 flatMap 方法是所讨论的两种类型之间的基础。 flatMap 有签名:

<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)

基本上允许您撰写 Optionals。您可以拥有一个Optional&lt;String&gt;,应用一个返回另一个Optional&lt;T&gt; 的函数,然后返回一个Optional&lt;T&gt;

这是一个关于 Monads 的 paper 可能会有所帮助。单子并没有那么可怕。关键特性是与上面显示的flatMap 具有相同签名的函数。如果你看到类似的东西,你很有可能找到了一个单子! Stream 因此是一个单子。

【讨论】:

猜你喜欢
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
相关资源
最近更新 更多