我有这个方法:
private def getMachineResponse(computeFunc: (Any*) => Option[List[MyThing]], any: Any*): Route = {
get {
val things = computeFunc(any)
// now do some stuff
}
}
我想用两个不同的computeFunc作为参数来调用这个方法,一个有2个参数,另一个有4个参数。但是调用不会编译。我正在尝试这个:
getMachineResponse(computeKnownItems, 1, "s")
其中computeKnownItems如下:
private def computeKnownItems(mtype: Int, id: String): Option[List[MyThing]] = {
// get the things
}
错误是“类型不匹配,找到(Int,String),必需(Any *)”。
有没有办法实现我正在尝试的,或者我应该为每种类型的computeFunc进行重载我需要传入? (如use(int,String)=>用于computeFunc的选项[List [MyThing]]然后创建一个带有computeFunc的重载:(int,int,int,String)=> ... etc)
谢谢。
稍后编辑:将参数名称更改为mtype(因为它在我的实际代码中,我在这里发布时太过美妙了!)
答案 0 :(得分:0)
首先......我没有看到这个东西编译。除co-variance
和contra-variance
问题外,还有很多问题。
最明显的问题是:
private def computeKnownItems(type: Int, id: String): Option[List[MyThing]] = {
// get the things
}
否...您无法使用type
作为标识符... type
是Scala中的关键字。
其他问题是,这样的事情无法编译:
def simple( func: ( Int* ) => Int, ints: Int* ): Int = func( ints )
error: type mismatch;
found : Seq[Int]
required: Int
def func( ints: Int* ): Int = func( ints )
这也不会:
def a( func: (Int*) => Int )( ints: Int* ): Int = func( ints )
error: type mismatch;
found : Seq[Int]
required: Int
def a( func: (Int*) => Int )( ints: Int* ): Int = func( ints )
^
这也不会:
scala> def fund( ints: Int* ): Int = ints.toList.sum
fund: (ints: Int*)Int
scala> def func( ints: Int* ): Int = fund( ints )
<console>:34: error: type mismatch;
found : Seq[Int]
required: Int
def func( ints: Int* ): Int = fund( ints )
^
以上所有问题都是该函数期望多个Int
参数,但是获得了一个参数,这是一个序列(*-parameters
在函数体中被隐式接收为Seq
)。传递可变大小参数的正确方法如下:
scala> def simple( func: ( Int* ) => Int, ints: Int* ): Int = func( ints: _* )
simple: (func: Int* => Int, ints: Int*)Int
_*
是特殊的annotation
,只能用于函数*-parameter
的参数。它使任何序列作为*-parameter
传递。
scala> val l = List( 4, 5, 6, 7, 3, 6, 3 )
l: List[Int] = List(4, 5, 6, 7, 3, 6, 3)
scala> def pp( ints: Int* ) = println( ints )
pp: (ints: Int*)Unit
// All Int* is implicitly received as a Seq[ Int ]
// ( WrappedArray[ int ] in this case ) in function body.
scala> pp( 4, 5, 6 )
WrappedArray( 4, 5, 6 )
// Received as List[ Int ] in this case
scala> pp( l: _* )
List(4, 5, 6, 7, 3, 6, 3)
scala> def a( ints: Int* ) = ints.sum
a: (ints: Int*)Int
// passing a list wont work
scala> a( l )
<console>:11: error: type mismatch;
found : List[Int]
required: Int
a( l )
^
// list passed as multiple parameters
scala> a( l: _* )
res8: Int = 34
现在,遇到主要问题......似乎你没有考虑过两个被称为co-variance
和contra-variance
的概念。
虽然这些都是非常一般的概念......让我在参考types
和classes
时解释这些概念。
可以说,我们有两种类型Animal
和Horse
,其中Horse
是Animal
或Horse <: Animal
的子类型。
现在,让我们考虑一个着名的类型 - List[ +T ]
。现在为什么+
签名......基本上+
表示List[ T ]
co-variant
为type T
,这意味着如果Horse <: Animal
则{ {1}}。这反过来意味着您可以在需要List[ Horse ] <: List[ Animal ]
实例的任何地方传递List[ Horse ]
的实例。如果你考虑一下,即使是英语也是如此。
但是,如果您谈论功能,它们是List[ Animal ]
,请考虑contra-variant
,这意味着如果Function1[ -T, +R ]
则Horse <: Animal
是Function1[ Animal, R ]
的子类型或Function1[ Horse, R ]
。
在您的情况下,您的类型Function1[ Animal, R ] <: Function1[ Horse, R ]
为(Any*) => Option[ List[ MyThing ] ]
wrt。它的参数意味着contra-variant
是(int, String) => Option[ List[ MyThing ] ]
的{{1}},这再次意味着您无法使用super-type
代替(Any*) => Option[ List[ MyThing ] ]
。
您可以做的是为(int, String) => Option[ List[ MyThing ] ]
(Any*) => Option[ List[ MyThing ] ]