如何通过 apply() 将协变可变参数传递给采用相同类型的协变可变参数的函数
请原谅任何错误的术语;我对 Scala 比较陌生。我会根据需要尽力澄清:)
我想设置一个函数[T <: Closeable, R],参数为T*,函数(T*)=>R,然后使用T* varargs调用该函数这是争论。这在代码中可能更清楚:
import java.io.Closeable
object Loans {
/**
* works fine, yay!
* Eg: using(new FileWriter(file)) { fw => ...use fw... }
*/
def using[T <: Closeable, R](c: T)(action: T => R): R = {
try {
action(c)
} finally {
if (null != c) c.close
}
}
/**
* Won't compile:
* type mismatch;
* found: closeables.type (with underlying type T*)
* required: T possible cause: missing arguments for method or constructor
*
* Intended usage is:
*
* usingva(new FileWriter(f), new OtherCloseable()) { ... }
*/
def usingva[T <: Closeable, R](closeables: T*)(action: (T*) => R): Unit = {
try {
action.apply(closeables)
} finally {
//...close everything...
}
}
}
不幸的是,usingva 版本无法编译,我对如何最好地完成可变参数贷款结构感到有些茫然。
非常感谢任何和所有的建议,ty。
Pardon any mistaken terminology; I am relatively new to Scala. I will endeavor to clarify as necessary :)
I want to setup a function[T <: Closeable, R], with parameters T*, function (T*)=>R, then invoke the function with the T* varargs as it's arguments. This is probably much clearer in code:
import java.io.Closeable
object Loans {
/**
* works fine, yay!
* Eg: using(new FileWriter(file)) { fw => ...use fw... }
*/
def using[T <: Closeable, R](c: T)(action: T => R): R = {
try {
action(c)
} finally {
if (null != c) c.close
}
}
/**
* Won't compile:
* type mismatch;
* found: closeables.type (with underlying type T*)
* required: T possible cause: missing arguments for method or constructor
*
* Intended usage is:
*
* usingva(new FileWriter(f), new OtherCloseable()) { ... }
*/
def usingva[T <: Closeable, R](closeables: T*)(action: (T*) => R): Unit = {
try {
action.apply(closeables)
} finally {
//...close everything...
}
}
}
Unfortunately the usingva version doesn't compile and I am at somewhat of a loss for how best to accomplish the varargs loan structure.
Any and all advice much appreciated, ty.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您必须在参数后面放置一个
:_*
来告诉编译器这不是一个单独的参数,而是整个参数序列:编辑评论中的第二个问题:< /em> 对于您的具体问题,不使用 varargs 可能是更好的选择,但直接将生成的
Seq
与部分函数结合使用:然后可以像这样使用:
不幸的是没有办法使此类型安全(即在编译时检查参数数量是否与函数匹配),但为所有数量的参数创建“使用”函数除外,因为 scala 中的类型级别不支持整数。与元组相同的问题...这就是为什么实际上有类
Tuple1
、Tuple2
、...、Tuple22
(是的...它们停在22)You will have to put a
:_*
behind the parameter to tell the compiler that this is not one single argument but the entire seq of arguments:Edit concerning your second question in the comment: For your specific problem it might be a better choice not to use varargs but the resulting
Seq
directly in combination with a partial function:this can then be used like this:
There is unfortunately no way to make this typesafe (ie. check that number of parameters match the function at compile time) except for creating
using
functions for all numbers of parameters because there is no integer support on type level in scala. Same problem like tuples... that is why there are actually classesTuple1
,Tuple2
, ... ,Tuple22
(Yes... they stop at 22)您需要将可变参数转换为类型系统的 Seq(Scala 内部所做的)。
You need to convert the varargs into a Seq for the type system (what Scala does internally).