I know this question has come up many times in different ways. But it is still not clear to me. Is there a way to achieve the following.
def foo(a:Int, b:Int) = {}
foo(a,b) //right way to invoke foo
foo(getParams) // is there a way to get this working without explicitly unpacking the tuple??
def getParams = {
//Some calculations
(a,b) //where a & b are Int
}
@dave-griffith полностью согласен.
Вы также можете вызвать:
Function.tupled(foo _)
Если вы хотите забрести на территорию «гораздо больше информации, чем я запрашивал», есть также методы, встроенные в частично применяемые функции (и в Функции
) для каррирования . Несколько примеров ввода/вывода:
scala> def foo(x: Int, y: Double) = x * y
foo: (x: Int,y: Double)Double
scala> foo _
res0: (Int, Double) => Double = <function2>
scala> foo _ tupled
res1: ((Int, Double)) => Double = <function1>
scala> foo _ curried
res2: (Int) => (Double) => Double = <function1>
scala> Function.tupled(foo _)
res3: ((Int, Double)) => Double = <function1>
// Function.curried is deprecated
scala> Function.curried(foo _)
warning: there were deprecation warnings; re-run with -deprecation for details
res6: (Int) => (Double) => Double = <function1>
Где каррированная версия вызывается с несколькими списками аргументов:
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> c(5)
res13: (Double) => Double = <function1>
scala> c(5)(10)
res14: Double = 50.0
Наконец, вы также можете отменить каррирование/размножение, если это необходимо. Функция
имеет для этого встроенные функции:
scala> val f = foo _ tupled
f: ((Int, Double)) => Double = <function1>
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> Function.uncurried(c)
res9: (Int, Double) => Double = <function2>
scala> Function.untupled(f)
res12: (Int, Double) => Double = <function2>
Function.tupled(foo _)(getParams)
или предложенный Дэйвом.
EDIT:
В ответ на ваш комментарий:
Что, если foo окажется конструктор какого-то класса?
В таком случае этот трюк не сработает.
Вы можете написать фабричный метод в объекте-компаньоне вашего класса, а затем получить версию его метода apply
с кортежами, используя один из вышеупомянутых методов.
scala> class Person(firstName: String, lastName: String) {
| override def toString = firstName + " " + lastName
| }
defined class Person
scala> object Person {
| def apply(firstName: String, lastName: String) = new Person(firstName, lastName)
| }
defined module Person
scala> (Person.apply _).tupled(("Rahul", "G"))
res17: Person = Rahul G
С case class
es вы бесплатно получаете сопутствующий объект с методом apply
, поэтому этот метод удобнее использовать с case class
es .
scala> case class Person(firstName: String, lastName: String)
defined class Person
scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)
Я знаю, что это дублирование кода, но, увы... у нас нет макросов (пока)! ;)
Это двухэтапная процедура. Сначала превратите foo в функцию, а затем вызовите для нее tuple, чтобы сделать ее функцией кортежа.
(foo _).tupled(getParams)