Wiem, że to pytanie pojawiało się wiele razy na różne sposoby. Ale nadal nie jest to dla mnie jasne. Czy jest sposób, aby osiągnąć następujące cele.
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
zwiadowca
źródło
źródło
Odpowiedzi:
To dwuetapowa procedura. Najpierw zamień foo w funkcję, a następnie wywołaj na niej krotkę, aby stała się funkcją krotki.
źródło
@ dave-griffith nie żyje.
Możesz również zadzwonić:
Function.tupled(foo _)
Jeśli chcesz zagłębić się w „dużo więcej informacji niż prosiłem”, istnieją również metody wbudowane w częściowo stosowane funkcje (i tak dalej
Function
) curry. Kilka przykładów wejścia / wyjścia: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>
W którym wersja curried jest wywoływana z wieloma listami argumentów:
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
Wreszcie, w razie potrzeby możesz również rozluźnić / rozluźnić.
Function
ma wbudowane do tego: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>
źródło
Function.tupled(foo _)(getParams)
lub ten zasugerowany przez Dave'a.EDYTOWAĆ:
Aby odpowiedzieć na Twój komentarz:
W takim przypadku ta sztuczka nie zadziała.
Możesz napisać metodę fabryczną w obiekcie towarzyszącym swojej klasy, a następnie uzyskać zwiniętą wersję jej
apply
metody przy użyciu jednej z wyżej wymienionych technik.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
Dzięki
case class
es otrzymujesz obiekt towarzyszący zapply
metodą za darmo, a zatem ta technika jest wygodniejsza w użyciu zcase class
es.scala> case class Person(firstName: String, lastName: String) defined class Person scala> Person.tupled(("Rahul", "G")) res18: Person = Person(Rahul,G)
Wiem, że to dużo duplikatów kodu, ale niestety ... nie mamy (jeszcze) makr! ;)
źródło
Person.tupled(("Rahul", "G"))
. Przydatne jest zrobienie tego również w odręcznych obiektach towarzyszących.Doceniam niektóre inne odpowiedzi, które były bliższe temu, o co prosiłeś, ale w bieżącym projekcie łatwiej było dodać kolejną funkcję, która konwertuje parametry krotki na parametry podziału:
def originalFunc(a: A, b: B): C = ... def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
źródło
Teraz możesz zaimplementować foo i sprawić, by przyjmował parametr klasy Tuple2 w ten sposób.
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)
źródło