如何通过apply()将co-variant varargs传递给一个采用相同类型的共同变量varargs的函数

S42*_*S42 1 scala

请原谅任何错误的术语; 我对Scala比较陌生.我会尽力澄清:)

我想设置一个函数[T <:Closeable,R],参数T*,function(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...
        }
    }
}    
Run Code Online (Sandbox Code Playgroud)

不幸的是,usingva版本没有编译,我在如何最好地完成varargs贷款结构方面有点亏本.

任何和所有建议都非常赞赏,ty.

Mar*_*ing 5

你将不得不:_*在参数后面告诉编译器这不是一个参数而是整个seq参数:

action(closeables :_*)
Run Code Online (Sandbox Code Playgroud)

编辑评论中的第二个问题:对于您的具体问题,最好不要使用varargs,而是Seq直接与部分函数结合使用:

def usingva[T <: Closeable, R](closeables: T*)(action: PartialFunction[Seq[T], R]): Unit = {
  try {            
    action(closeables) 
  } 
  finally {
    //...close everything... 
  } 
}
Run Code Online (Sandbox Code Playgroud)

这可以像这样使用:

usingva(new FileWriter(file), new FileWriter(file) {
   case Seq(fw1,fw2) => ... // You can use fw1 and fw2 seperately here
}
Run Code Online (Sandbox Code Playgroud)

不幸的是没有办法让这个类型安全(即检查数量的参数匹配在编译时的功能),除了创造using了所有的参数号功能,因为有在阶式液位没有整数支持.像元组同样的问题...这就是为什么实际上存在着阶级Tuple1,Tuple2......, Tuple22(是的......他们止步于22)