[英]Scala - Make signature of function parameter f of higher order function g dependent on varars of g
I am trying to define a higher order function f
which accepts a variable number of parameters args
of type Wrapper[T]*
and a function parameter g
in Scala. 我正在尝试定义一个高阶函数
f
,该函数接受变量数量为Wrapper[T]*
类型的参数args
和Scala中的函数参数g
。
The function f
should decapsulate each object passed in args
and then call g
with the decapsulated parameters. 函数
f
应该解封装在args
传递的每个对象,然后使用解封装的参数调用g
。 Therefore, g
has to accept exactly the same number of parameters of type T
as args
contains. 因此,
g
必须接受与args
包含的T
类型参数数量完全相同的参数。
The closest thing I could achieve was to pass a Seq[T]
to g
and to use pattern matching inside of g
. 我能实现的最接近的事情是将
Seq[T]
传递给g
并在g
内使用模式匹配。 Like the following: 如下所示:
f("This", "Is", "An", "Example")(x => x match {
case Seq(a:String, b:String, c:String): //Do something.
})
With f
defined like: 用
f
定义如下:
def f[V](args: Wrapper[T]*)
(g: (Seq[T]) => (V)) : V = {
val params = args.map(x => x.unwrap())
g(params)
}
g
by using type inference, but only if the number of parameters is fixed. g
签名中的类型,但前提是参数的数量是固定的。 How could this be done in this case? args: Wrapper[_]*
. args: Wrapper[_]*
,则可以将不同类型的参数传递给varargs args: Wrapper[_]*
。 Additionally, casting the result of x.unwrap
to AnyRef
and using pattern matching in g
is necessary. x.unwrap
将AnyRef
的结果x.unwrap
为AnyRef
并在g
使用模式匹配。 This, however, completely breaks type inference and type safety. I am also considering the use of scala makros to accomplish these tasks. 我也在考虑使用scala makros来完成这些任务。
Did I get you right? 我说对了吗? I replaced your
Wrapper
with some known type, but that doesn't seem to be essential. 我用某种已知的类型替换了您的
Wrapper
,但这似乎不是必需的。
def f[T, V](args: T*)(g: PartialFunction[Seq[T], V]): V = g(args)
So later you can do this: 因此,稍后您可以执行以下操作:
f(1,2,3) { case Seq(a,b,c) => c } // Int = 3
Okay, I've made my own Wrapper
to be totally clear: 好的,我已经明确了自己的
Wrapper
:
case class Wrapper[T](val x:T) {
def unwrap = x
}
def f[V](args: Wrapper[_]*)(g: PartialFunction[Seq[_], V]): V =
g(args.map(_.unwrap))
f(Wrapper("1"), Wrapper(1), Wrapper(BigInt(1))) {
case Seq(s: String, i: Int, b: BigInt) => (s, i, b)
} // res3: (String, Int, BigInt) = (1,1,1)
Regarding your concerns about type safety and conversions: as you can see, there aren't any explicit conversions in the code above, and since you are going to pattern-match with explicitly defined types, you may not to worry about these things - if some items of an undefined origin are going to show in your input, scala.MatchError
will be thrown. 关于类型安全性和转换的担忧:如您所见,上面的代码中没有任何显式转换,并且由于您要与显式定义的类型进行模式匹配,因此您不必担心这些事情-如果输入
scala.MatchError
显示一些未定义来源的项目, scala.MatchError
将被抛出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.