来自另一个类的Scala方法参考?

时间:2018-07-09 08:08:28

标签: scala syntax

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.:+) 

2 个答案:

答案 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)(_ :+ _)