scala tuple unpacking

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
}
90
задан scout 25 August 2010 в 16:15
поделиться

3 ответа

@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>

54
ответ дан 24 November 2019 в 07:02
поделиться

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 classes вы бесплатно получаете сопутствующий объект с методом apply, поэтому этот метод удобнее использовать с case classes .

scala> case class Person(firstName: String, lastName: String)
defined class Person

scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)

Я знаю, что это дублирование кода, но, увы... у нас нет макросов (пока)! ;)

20
ответ дан 24 November 2019 в 07:02
поделиться

Это двухэтапная процедура. Сначала превратите foo в функцию, а затем вызовите для нее tuple, чтобы сделать ее функцией кортежа.

(foo _).tupled(getParams)
103
ответ дан 24 November 2019 в 07:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: