Как передать ко-вариантные varargs через apply () в функцию, которая принимает ко-вариантные varargs того же типа - PullRequest
1 голос
/ 08 марта 2011

Прошу прощения за любую ошибочную терминологию; Я относительно новичок в Скале. Я постараюсь уточнить при необходимости:)

Я хочу установить функцию [T <: Closeable, R] с параметрами T *, function (T *) => R, а затем вызвать функцию с переменными T * в качестве аргументов. Это, вероятно, намного понятнее в коде:

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.

Любой и все советы высоко ценится, ты.

Ответы [ 2 ]

5 голосов
/ 08 марта 2011

Вам нужно будет поставить :_* за параметром, чтобы сообщить компилятору, что это не один аргумент, а весь набор аргументов:

action(closeables :_*)

Отредактируйте ваш второй вопрос в комментарии: Для вашей конкретной проблемы может быть лучше выбрать не varargs, а полученный Seq напрямую в сочетании с частичной функцией:

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 для всех чисел параметров, потому что в scala отсутствует целочисленная поддержка на уровне типов , Та же проблема, что и у кортежей ... вот почему на самом деле существуют классы Tuple1, Tuple2, ..., Tuple22 (Да ... они останавливаются на 22)

1 голос
/ 08 марта 2011

Вам нужно преобразовать varargs в Seq для системы типов (что делает Scala внутри).

action :  Seq[T] => R
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...