2015-07-29 3 views
0

Это вопрос, связанный с Scala.Передача всех аргументов функции как одного массива

Предположим, что у вас есть функция (которую вы не можете изменить) несколько входов, например:

def test(x1: Int, x2:Int, x3: Int, x4: Int, x5: Int) = { 
    //Some logic 
} 

И предположим, что у вас есть все входы для этой функции в одном массиве, например:

val inputs = Array(1, 2, 3, 4, 5) 

Есть ли способ вызвать test с помощью этого единственного массива входов без явной вставки отдельных элементов массива (как в test(inputs(0),inputs(1),inputs(2),inputs(3),inputs(4)))?

Это особенно важно для случая, когда я не знаю количества входов и количества элементов в массиве заранее (но знаю, что они совпадают).

ответ

3

Нет, это невозможно. Можно использовать массив для функции, которая ожидает varargs, используя синтаксис :_*. Кроме того, ваш вопрос противоречива:

тот случай, когда я не знаю, количество входов и количество элементов в массиве заранее (но знаю, что они совпадают)

Как не могли бы вы узнать количество входов или элементов, но знаете, что они соответствуют?

+0

Я использую несколько функций, написанных кем-то другим, которые соответствуют определенным таблицам в базе данных SQL (количество аргументов для каждой из этих функций совпадает с количеством столбцов в соответствующих таблицах). Я обращаюсь к таблицам через JDBC, а затем хочу запустить эти функции для обработки результатов моих запросов. Возможно ли, по крайней мере, создать внутреннее расширение «входов» на «входы (0), входы (1), ...'? Например. что-то вроде строк 'test (for (i <- input) i)'? – verse

+0

@verse вы считали, что просто не делаете этого? Честно говоря, это звучит как самый необоснованный подход ко всему, что я когда-либо слышал. Выяснение того, как передать массив в качестве аргументов этой функции, является наименьшим из ваших забот. Вы спрашивали кого-то, почему они так мало уважают вас? – LuxuryMode

1

Вы можете выполнить эту функцию, а затем использовать одно из предлагаемых решений here.

Например, с помощью this technique:

class Acc[T](f: Function1[T, _]) { 
    private[this] var ff: Any = f 
    def apply(t: T): this.type = { 
    ff = ff.asInstanceOf[Function1[T,_]](t) 
    this 
    } 
    def get = ff match { 
    case _: Function1[_,_] => sys.error("not enough arguments") 
    case res => res.asInstanceOf[T] 
    } 
} 

def test(x1: Int, x2:Int, x3: Int, x4: Int, x5: Int) = { 
    //Some logic 
} 

val inputs = Array(1, 2, 3, 4, 5) 

inputs.foldLeft(new Acc((test _).curried))((acc, i) => acc(i)).get 

не очень безопасно, но он должен работать

+0

Gabriele, и будет ли это работать, если бы вместо функции у меня был класс class test (x1: Int, x2: Int, x3: Int, x4: Int, x5: Int) 'и хотел запустить конструктор с одним массив входов? – verse

+0

Да, вы можете создать конструктор: http://stackoverflow.com/questions/3862717/scala-curried-constructors –

0

Вы можете использовать Java отражение (или Scala отражение, но один в Java для этого достаточно). Ниже это быстрый и грязный раствор, который предполагает, что вы есть класс Test, который содержит ровно один test метод:

val m = classOf[Test]. 
    getMethods.find(_.getName == "test"). 
    getOrElse(throw new Exception("No method called test")) 

// inputs must be Array[Object], not Array[Int] as in your example 
m.invoke(instanceOfTest, inputs) 

Это редко бывает хорошей идеей, однако.

Смежные вопросы