3

尽管阅读了 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)(_ + _)

此外,有时我看到的代码显示的方法实际上要么在其签名中采用零个参数,要么比我期望它们采用的参数少一个,并且仍然使用点表示法正确地采用参数。这是如何运作的?我问这个是因为这些方法适用于点符号,所以也许如果我写了类似的东西,我可以解决我的问题。

4

2 回答 2

5

对于您问题的第一部分,您可能需要查看隐式类

  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

您可以使用隐式包装器“丰富”现有类来“添加”新方法。

至于第二部分,可能你想要隐式参数。隐式参数是按类型从当前范围推导出来的。下面的示例中使用了一些预定义的隐式值,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
于 2015-07-25T00:57:40.827 回答
1

soong 指出,我实际上正在寻找“Pimp my library”模式,然后我查找了该模式,并像这样实现以处理有问题的方法:

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))
}

据我了解,允许点表示法的关键要素是拥有一个类构造,该构造采用我想要“拉皮条”的类型的参数。在这种情况下,我有一个列表,我想foldRVL在写下列表后调用列表,如下所示 List(something).foldRVL(z)(f: A => B):因此,我需要一个带有List[A]参数的类,以便能够在第一个代码片段中编写类似的方法。

使用该implicit关键字,以便我可以向现有方法添加方法,class List而无需创建单独的方法库。任何时候List发现foldRVLa在. 因此,它将查找在作用域中定义的任何隐式方法,这些方法具有方法并以 a作为参数,并发现具有已定义的方法并以 a 为参数。因此,我现在可以写:BlingListListclass ListfoldRVLListimplicit class BlingListfoldRVLList[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

“一个 Scala 2.10 隐式类示例”对此进行了更深入的介绍。那篇文章中我最喜欢的指针是将您希望在当前包中使用的所有隐式类以及 a 内的任何子包中package object,这样您就不必使用隐式类定义来混淆您的任何类或对象,您也不必导入它们。由于package object.

于 2015-07-25T00:53:55.483 回答