Я знаю, что этот вопрос поднимался много раз по-разному. Но мне это все еще непонятно. Есть ли способ добиться следующего.
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
}
scala
parameters
tuples
разведчик
источник
источник
Ответы:
Это двухэтапная процедура. Сначала превратите foo в функцию, а затем вызовите для нее кортеж, чтобы он стал функцией кортежа.
источник
@ Дэйв-Гриффит мертв.
Вы также можете позвонить:
Function.tupled(foo _)
Если вы хотите исследовать территорию, «где больше информации, чем я просил», существуют также методы, встроенные в частично применяемые функции (и другие
Function
) для каррирования. Несколько примеров ввода / вывода: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
Наконец, вы также можете развернуть / развернуть, если необходимо.
Function
для этого есть встроенные функции: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)
или тот, который предложил Дэйв.РЕДАКТИРОВАТЬ:
Чтобы ответить на ваш комментарий:
В таком случае этот трюк не сработает.
Вы можете написать фабричный метод в сопутствующем объекте вашего класса, а затем получить кортежную версию его
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)
Я знаю, что это много дублирования кода, но, увы ... у нас нет макросов (пока)! ;)
источник
Person.tupled(("Rahul", "G"))
такой же, как и в рукописных сопутствующих объектах.Я ценю некоторые другие ответы, которые были ближе к тому, что вы просили, но мне было проще добавить в текущий проект еще одну функцию, которая преобразует параметры кортежа в параметры разделения:
def originalFunc(a: A, b: B): C = ... def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
источник
Теперь вы можете реализовать foo и заставить его принимать параметр класса Tuple2 вот так.
def foo(t: Tuple2[Int, Int]) = { println("Hello " + t._1 + t._2) "Makes no sense but ok!" } def getParams = { //Some calculations val a = 1; val b = 2; (a, b) //where a & b are Int } // So you can do this! foo(getParams) // With that said, you can also do this! foo(1, 3)
источник