假设我有两种方法:
def a(s: String) = s + "..."
def b(s: String) = s + ",,,"
我想创建第三种方法,它将调用两种方法:
def c (s: String) = a(b(s))
我如何用惯用的Scala方式做到这一点?
我认为最好将这些函数聚合到某个List中,然后依次应用它们:
List(a_, b_)
答案 0 :(得分:3)
我认为最好将这些功能聚合到一些List和 然后依次应用它们。
通过指定预期类型,您可以获得一些帮助:
scala> val fs: List[String => String] = List(a,b)
fs: List[String => String] = List(<function1>, <function1>)
scala> fs.foldLeft("something")((s,f) => f(s))
res0: String = something...,,,
答案 1 :(得分:2)
以下是如何将一组功能组合成一个:
// a() and b() are as defined in the question
// the following is equivalent to newfunc(x) = b(a(x))
val newFunc: String => String = List( a _, b _).reduce( _ andThen _ )
您甚至可以创建一个通用函数来组合它们:
def functionChaining[A]( functions: A => A *): A => A = functions.reduce( _ andThen _ )
或使用foldLeft
:
def functionChaining[A]( functions: A => A *): A => A = functions.foldLeft( (x:A) => x )( _ andThen _ )
以下是如何在REPL上使用它的示例:
scala> val newFunc: String => String = functionChaining( (x:String) => x + "---", (x:String) => x * 4)
scala> newFunc("|")
res12: String = |---|---|---|---
答案 2 :(得分:1)
许多答案都使用andThen
,但这会给你
b(a(s))
鉴于你想要
a(b(s))
compose
是要走的路(好吧,或者反转清单,但重点是什么?)
def c(s: String) = List[String => String](a, b).reduce(_ compose _)(s)
// or alternatively
def c(s: String) = List(a _, b _).reduce(_ compose _)(s)
结果
c("foo") // foo,,,...
现在,谈到什么是惯用语,我相信
a(b(s))
比
更具惯用性和可读性List(a _, b _).reduce(_ compose _)(s)
这显然取决于你正在编写的功能的数量。如果你有
a(b(c(d(e(f(g(h(s))))))))
然后
List[String => String](a, b, c, d, e, f, g, h).reduce(_ compose _)(s)
可能更整洁,更具惯用性。
答案 3 :(得分:0)
如果确实认为你需要这样做:
val c = a _ andThen b
// (The signature is:)
val c:(String)=>String = a _ andThen b
或者,更明显的是:
def d(s:String) = a _ andThen b
答案 4 :(得分:0)
如果首选链接应用程序,则以下工作原理。警告 - 隐含的语法有点难看;这是一种结构类型,使用反射。
object string {
implicit def aPimp(s: String) = new {
def a = "(a- " + s + " -a)"
}
implicit def bPimp(s: String) = new {
def b = "(b- " + s + " -b)"
}
}
scala> import string._
scala> "xyz".a.b
res0: String = (b- (a- xyz -a) -b)
scala> "xyz".b.a
res1: String = (a- (b- xyz -b) -a)
在我看来,如果不是因为丑陋的语法,这将是惯用的scala。