首先...我没有看到这个东西在编译。除了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 然后List[ Horse ] <: List[ Animal ]。这反过来意味着您可以在需要List[ Animal ] 实例的任何地方传递List[ Horse ] 的实例。如果你仔细想想,即使是英语也是如此。
但是,如果您谈论函数,它们是contra-variant,考虑Function1[ -T, +R ],这意味着如果Horse <: Animal 那么Function1[ Animal, R ] 是Function1[ Horse, R ] 或Function1[ Animal, R ] <: Function1[ Horse, R ] 的子类型。
在您的情况下,您的类型 (Any*) => Option[ List[ MyThing ] ] 是 contra-variant wrt。它的参数意味着(int, String) => Option[ List[ MyThing ] ] 是super-type 的(Any*) => Option[ List[ MyThing ] ] 这再次意味着你不能使用(int, String) => Option[ List[ MyThing ] ] 代替(Any*) => Option[ List[ MyThing ] ]。
你可以做的是为Map[ String, Any ]定义函数
def getMachineResponse(computeFunc: ( Map[ String, Any ] ) => Option[List[MyThing]], any: Map[ String, Any ] ): Route = {
get {
val things = computeFunc(any)
// now do some stuff
}
}
private def computeKnownItems(myMap: Map[ String, Any] ): Option[ List[ MyThing ] ] = {
val myType = myMap.get( "type" ).asInstanceOf[ Int ]
val myId = myMap.get( "id" ).asInstanceOf[ String ]
// get the things
}