Scala的方法参考如何工作? 假设有以下列表:
val list12 = List(1, 2)
val list012 = 0 :: list1 //insert at head
val list123 = list1 :+ 3 //insert at end
假设有一个接受元素,列表的高阶函数,还有一个将元素添加到列表并返回新列表的函数:
def append[T](e: T, list: List[T], fun: (List[T], T) => List[T]): List[T] = {
fun(list, e)
}
如果要在本地定义这样的方法:
def appendAtHead[T](list: List[T], e: T): List[T] = {
e :: list
}
然后调用将很简单:
append(0, list12, appendAtHead[Int])
但是如何引用现有方法::
和:+
?以下调用不起作用(例如在Java中):
append(0, list12, List.::)
append(3, list12, SeqLike.:+)
答案 0 :(得分:2)
在Scala中,类上的方法并不等同于将类作为第一个参数的自由函数。您无法将对象与方法解除绑定。
相反,您必须创建一个匿名函数来调用对象上的方法,如下所示:
append(0, list12, _.::(_))
append(0, list12, _ :+ _)
在当前代码中,List.::
指向List
类的伴随对象,并且其中不包含名为::
的函数。
答案 1 :(得分:1)
Scala没有将方法引用与普通的lambda分开,就像Java和Kotlin一样(在类似append(0, list12, appendAtHead[Int])
的情况下,它进行eta扩展,方法名称是写lambda的一种简短方法,因为Specification 6.26.5中所述)。
因此请改用lambdas。对于::
,它不如:+
方便,因为参数的顺序错误,因此,但是(实际上,这是因为List.::
在Java中也不起作用::
is right-associative, which also allows to write _.::(_)
in Scala):
append[Int](0, list12, (x, y) => y :: x) // or append(0, list12, (x: List[Int], y: Int) => y :: x)
append[Int](3, list12, _ :+ _)
或者如果您通过将fun
移动到单独的参数列表中来帮助进行推断,
def append[T](e: T, list: List[T])(fun: (List[T], T) => List[T]): List[T] = ...
append(0, list12)((x, y) => y :: x)
append(3, list12)(_ :+ _)