尽管多次阅读the Scala Style Guide - Method Invocation,我已经对此感到困惑了一段时间。
我希望能够调用此方法
def foldRVL[A,B](l: List[A], z: B)(f: (A, B) => B) = //"Right-Via-Left"
l.reverse.foldLeft(z)((a, b) => f(b, a))
使用点符号,例如List(1,2,3).foldRVL(0)(_ + _)
。
而不是这样:foldRVL(List(1,2,3), 0)(_ + _)
。
此外,有时我看到的代码显示的方法实际上是在签名中采用零参数,或者比我预期的要少一个参数,并且仍然使用点符号正确地获取参数。这是如何运作的?我问这个是因为这些方法使用点符号,所以也许如果我写了类似的东西我可以解决我的问题。
答案 0 :(得分:5)
对于问题的第一部分,您可能需要查看developer docs:
implicit class RichRVLList[A](l:List[A]) {
def foldRVL[B](z: B)(f: (A, B) => B) = //"Right-Via-Left"
l.reverse.foldLeft(z)((a, b) => f(b, a))
}
List(1,2,3).foldRVL(1)(_ + _) // output: res0: Int = 7
你可以"丰富"现有的类使用隐式包装器来"添加"新方法。
至于第二部分,你可能想要implicit classes。隐式参数是按类型从当前范围推导出来的。在下面的示例中使用了一些预定义的隐式值,例如Numerics
:
def product[T](els:TraversableOnce[T])(implicit num:Numeric[T]) = {
els.fold(num.one)((x1, x2) => num.times(x1, x2))
}
product(List(1, 2, 3)) // res1: Int = 6
product(List(1, 2.5, 3)) //res2: Double = 7.5
答案 1 :(得分:1)
implicit class BlingList[+A](l: List[A]) {
def foldRVL[B](z: B)(f: (A, B) => B): B = //"Right-Via-Left"
l.foldLeft(z)((a, b) => f(b, a))
}
据我所知,允许点符号的关键因素是有一个类构造,它接受我想要的类型参数' pimped'。在这种情况下,我有一个列表,我想在列表向下写入列表后调用foldRVL
,如下所示:
List(something).foldRVL(z)(f: A => B)
。
因此,我需要一个为List[A]
参数提供的类,以便能够在第一个代码片段中编写类似的方法。
使用implicit
关键字,以便我可以向现有class List
添加方法,而无需创建单独的方法库。每当在List
之前找到foldRVL
作为前缀时,它都会被隐式转换为BlingList
,因为编译器会看到一个List
附加到一个没有的方法存在于class List
中。因此,它将查找范围中定义的具有foldRVL
方法并以List
作为参数的任何隐式方法,并且它发现implicit class BlingList
具有方法foldRVL
定义并获取List[A]
。因此,我现在可以写:
List(1,2,3).foldRVL(0)(_ + _) // in some IDE's, foldRVL will be underlined to show that
res0: Int = 6 // an implicit conversion is being made
"A Scala 2.10 implicit class example"对此有更深入的了解。我最喜欢的那篇文章的指针是将你期望在当前包中使用的所有隐式类以及package object
内的任何子包放在一起,这样你就不必弄乱你的任何类了或具有隐式类定义的对象,也不必导入它们。由于package object
。