【问题标题】:Functional programming idiom for applying a series of void functions to a single value将一系列 void 函数应用于单个值的函数式编程习惯用法
【发布时间】:2018-05-12 11:53:22
【问题描述】:

给定一个值 foo 和一个 StreamConsumer<Foo> void 函数,将每个函数应用于该值的最简洁方法是什么?现在我有

consumers.forEach(c -> c.accept(foo));

这并不可怕,但我怀疑可能有某种方法可以将其翻转过来并仅使用方法引用(没有明确的 lambda)来完成。可能是单例列表和zip()

我会很高兴有一个直接的 Java 8 答案、Vavr 或 Scala。

(请注意,这不是折叠,或者至少不是通常的 foldLeft/foldRight 应用程序;如果有返回值,我会丢弃它们,而不是迭代它们。)

【问题讨论】:

  • 通过Consumer#andThen(Consumer after)连接是一个有效的选项吗?
  • 有趣的问题,但在 Java 中,没有什么比您已经拥有的更简单、简洁或在典型 VM 中表现出色了。
  • forEach 和 void 函数不用于函数式成语......您正在寻找不存在的东西
  • @naomik 好的,如果你发现它不存在,就假装它是functions.map(f -> f.apply(foo))
  • @naomik 考虑一下 IO monad。

标签: java scala functional-programming vavr


【解决方案1】:

您可以通过Consumer.andThen 方法减少您的消费者,然后将结果消费者应用到foo 参数:

consumers.reduce(Consumer::andThen).ifPresent(c -> c.accept(foo));

但是这种方法和你的没有区别,而且你的更短。

【讨论】:

    【解决方案2】:

    在 Scala 中你应该可以做到

    consumers.foreach(_.accept(foo));
    

    【讨论】:

    • 这正是 OP 所做的,它就在问题中。
    • 不完全一样。它编译为相同的字节码,但使用不同的语法。我并不是说这是革命性的,但大卫要求以更简洁的方式做到这一点,而且更短,不是吗?
    • 确实如此,但如果你真的想实现简洁的 Scala,你会使用foreachforEach 不是 Scala)并且你会去掉分号;(Scala 不是' t Java)。即使在那之后,如果我们打一轮code golf,我仍然会让你击败2杆:for(c<-consumers)c.accept(foo)
    • 是的。我可以用consumers.foreach(_ accept foo) 更接近一点。后面还有一个字符:)。 consumers foreach _ accept foo 可能行不通:)。
    • 我建议我采用 Scala 解决方案的原因是,从 Scala 转换到 Vavr 通常很简单,而且这里的 Scala 程序员可能比(优秀的)函数式 Java 程序员更多。这个答案“更简洁”,但这仅仅是因为 Scala 更简洁。
    【解决方案3】:

    我认为这里真正关心的是返回 void 的方法是代码异味。为什么他们不能返回有用的东西,或者至少执行它们的副作用然后返回原始值,这样可以更好地链接。我认为这将是一种更可取的方法,但除此之外,我认为 forEach 方法还可以。

    【讨论】:

    • 这会让代码更简洁吗?假设我(在其他地方,因此不计入简洁性)将每个 Consumer<Foo> 包装为 Function<Foo, Foo>Stream<Function<Foo, Foo>> functions = consumers.map(c -> (f) -> { c.accept(f); return f; }); — 将这些链接起来的简洁方法是什么?
    猜你喜欢
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 2018-09-26
    • 2019-03-13
    • 2019-03-10
    相关资源
    最近更新 更多