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

时间:2011-03-08 17:56:17

标签: scala

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

我想设置一个函数[T&lt ;: 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...
        }
    }
}    

不幸的是,usingva版本没有编译,我对如何最好地完成varargs贷款结构感到有些失望。

任何和所有建议都非常感谢,ty。

2 个答案:

答案 0 :(得分:5)

你必须在参数后面放一个:_*来告诉编译器这不是一个参数而是整个seq参数:

action(closeables :_*)

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

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

然后可以这样使用:

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

遗憾的是,没有办法使这种类型安全(即检查参数的数量是否与编译时的函数匹配),除了为所有数量的参数创建using函数,因为类型级别没有整数支持在斯卡拉。像元组一样的问题...这就是为什么实际上有类Tuple1Tuple2,...,Tuple22(是的......它们在22点停止)

答案 1 :(得分:1)

您需要将varargs转换为类型系统的Seq(Scala在内部执行的操作)。

action :  Seq[T] => R