在尝试以功能样式编写代码时,经常遇到要使用两个函数将一个集合或流映射到另一个集合或流的情况:一个函数应用于传递给定谓词的元素,另一个函数应用于失败的元素。 这两个函数均产生一个公共输出,应将其收集以进行进一步处理。

这是Java中人为的示例。

Stream.of("foo", "bar", "baz", "qux")
      .map(it -> it.startsWith("ba") ? it.toUpperCase() : new StringBuilder(it).reverse())
      .forEach(System.out::println);

与Groovy中的示例相同。

["foo", "bar", "baz", "qux"]
      .collect{ it.startsWith("ba") ? it.toUpperCase() : it.reverse() }
      .each{ println(it) }

我的问题是关于用于实现此映射的条件(三元)语句。 是否有功能上的惯用法来实现这种映射而无需借助分支逻辑?

===============>>#1 票数:1

您始终可以使用另一个函数对表达式进行抽象。 由于您标记了与语言无关的问题,因此我使用可在您喜欢的浏览器中执行的Javascript编码示例-希望这样可以:

 // select :: (a -> Boolean, a -> b, a -> b) -> a -> b const select = (p, f, g) => x => p(x) ? f(x) : g(x); // mapSelect :: (a -> Boolean, a -> b, a -> b) -> [a] -> [b] const mapSelect = (p, f, g) => xs => xs.map(select(p, f, g)); const reverse = s => s.split("").reverse().join(""); const toUpperCase = s => s.toUpperCase(); const startsWith = s => t => t.indexOf(s) === 0 const xs = ["foo", "bar", "baz", "qux"]; console.log( mapSelect(startsWith("ba"), toUpperCase, reverse) (xs) ); 

显然, mapSelect不会将您从条件运算符中解救出来。 这只是抽象的另一层。 由于它不像map那样常见,因此您尤其增加了同事的认知负担而没有增加太多。

结论:我会坚持使用显式条件运算符,而不是伪装分支逻辑。

  ask by jaco0646 translate from so

未解决问题?本站智能推荐: