Scala:如何创建一个允许我在调用时使用点符号的函数?
Scala: How can I create a function that allows me to use dot notation when calling it?
尽管阅读了 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)(_ + _)
。
此外,有时我看到代码显示的方法实际上要么在其签名中采用零参数,要么比我期望的参数少一个,但仍然使用点符号正确地采用参数。这是如何运作的?我问这个是因为这些方法使用点符号,所以也许如果我写类似的东西我可以解决我的问题。
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))
}
据我所知,允许点符号的关键因素是有一个 class 构造,它采用我想要 'pimped' 类型的参数。在这种情况下,我有一个列表,我想在写下列表后在列表上调用 foldRVL
,如下所示:
List(something).foldRVL(z)(f: A => B)
。
因此,我需要一个带有 List[A]
参数的 class,以便我能够编写类似于第一个代码片段中的方法。
使用 implicit
关键字以便我可以将方法添加到现有的 class List
而无需创建单独的方法库。任何时候在 foldRVL
之前发现 List
前缀,它将被隐式转换为 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" 对此进行了更深入的探讨。 post 中我最喜欢的指针是将所有你希望在当前包中使用的隐式 class 和 package object
中的任何子包放在一起,这样你就不会必须使用隐式 class 定义来混淆任何 classes 或对象,也不必导入它们。由于 package object
.
,他们使用相同的包这一事实将自动导入它们
对于问题的第一部分,您可能需要查看 implicit classes:
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
您可以 "enrich" 现有 class 使用隐式包装器 "add" 新方法。
至于第二部分,可能你想要implicit parameters。隐式参数是按类型从当前范围推导出来的。下面的示例中使用了一些预定义的隐式值,例如 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
尽管阅读了 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)(_ + _)
。
此外,有时我看到代码显示的方法实际上要么在其签名中采用零参数,要么比我期望的参数少一个,但仍然使用点符号正确地采用参数。这是如何运作的?我问这个是因为这些方法使用点符号,所以也许如果我写类似的东西我可以解决我的问题。
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))
}
据我所知,允许点符号的关键因素是有一个 class 构造,它采用我想要 'pimped' 类型的参数。在这种情况下,我有一个列表,我想在写下列表后在列表上调用 foldRVL
,如下所示:
List(something).foldRVL(z)(f: A => B)
。
因此,我需要一个带有 List[A]
参数的 class,以便我能够编写类似于第一个代码片段中的方法。
使用 implicit
关键字以便我可以将方法添加到现有的 class List
而无需创建单独的方法库。任何时候在 foldRVL
之前发现 List
前缀,它将被隐式转换为 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" 对此进行了更深入的探讨。 post 中我最喜欢的指针是将所有你希望在当前包中使用的隐式 class 和 package object
中的任何子包放在一起,这样你就不会必须使用隐式 class 定义来混淆任何 classes 或对象,也不必导入它们。由于 package object
.
对于问题的第一部分,您可能需要查看 implicit classes:
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
您可以 "enrich" 现有 class 使用隐式包装器 "add" 新方法。
至于第二部分,可能你想要implicit parameters。隐式参数是按类型从当前范围推导出来的。下面的示例中使用了一些预定义的隐式值,例如 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