这个表达式可以用Factor 编程语言非常优雅地编写- 一种以函数组合为处理方式的语言,并且大多数代码都是以无点方式编写的。堆栈语义和行多态性促进了这种编程风格。这就是您的问题的解决方案在 Factor 中的样子:
# We find the longer of two lists here. The expression returns { 4 5 6 7 8 }
{ 1 2 3 } { 4 5 6 7 8 } [ [ length ] bi@ > ] 2keep ?
# We find the shroter of two lists here. The expression returns { 1 2 3 }.
{ 1 2 3 } { 4 5 6 7 8 } [ [ length ] bi@ < ] 2keep ?
我们感兴趣的是组合子2keep
。它是一个“保留数据流组合器”,这意味着它在对它们执行给定功能后保留其输入。
让我们尝试将这个解决方案翻译(某种程度)到 Scala。
首先,我们定义了一个保留 arity-2 的组合器。
scala> def keep2[A, B, C](f: (A, B) => C)(a: A, b: B) = (f(a, b), a, b)
keep2: [A, B, C](f: (A, B) => C)(a: A, b: B)(C, A, B)
和一个eagerIf
组合器。if
作为控制结构不能用于函数组合;因此这个结构。
scala> def eagerIf[A](cond: Boolean, x: A, y: A) = if(cond) x else y
eagerIf: [A](cond: Boolean, x: A, y: A)A
还有,on
组合器。由于它与 Scalaz 中同名的方法发生冲突,我将upon
改为命名它。
scala> class RichFunction2[A, B, C](f: (A, B) => C) {
| def upon[D](g: D => A)(implicit eq: A =:= B) = (x: D, y: D) => f(g(x), g(y))
| }
defined class RichFunction2
scala> implicit def enrichFunction2[A, B, C](f: (A, B) => C) = new RichFunction2(f)
enrichFunction2: [A, B, C](f: (A, B) => C)RichFunction2[A,B,C]
现在把这台机器投入使用!
scala> def length: List[Int] => Int = _.length
length: List[Int] => Int
scala> def smaller: (Int, Int) => Boolean = _ < _
smaller: (Int, Int) => Boolean
scala> keep2(smaller upon length)(List(1, 2), List(3, 4, 5)) |> Function.tupled(eagerIf)
res139: List[Int] = List(1, 2)
scala> def greater: (Int, Int) => Boolean = _ > _
greater: (Int, Int) => Boolean
scala> keep2(greater upon length)(List(1, 2), List(3, 4, 5)) |> Function.tupled(eagerIf)
res140: List[Int] = List(3, 4, 5)
这种方法在 Scala 中看起来不是特别优雅,但至少它向您展示了另一种做事方式。