Frage Warum bietet Scala sowohl mehrere Parameterlisten als auch mehrere Parameter pro Liste? [Duplikat]


Diese Frage hat hier bereits eine Antwort:

Mehrere Parameterlisten, z.B. def foo(a:Int)(b:Int) = {} und mehrere Parameter pro Liste, z.B. def foo(a:Int, b:Int) = {} sind semantisch äquivalent, soweit ich das beurteilen kann, und die meisten funktionalen Sprachen haben nur eine Möglichkeit, mehrere Parameter zu deklarieren, z. F #.

Der einzige Grund, warum ich beide Arten von Funktionsdefinitionen unterstützen kann, ist syntaxähnliche Spracherweiterungen mit einer Parameterliste, die nur einen Parameter enthält.

def withBufferedWriter(file: File)(block: BufferedWriter => Unit)

kann jetzt mit dem Syntax-Looking aufgerufen werden

withBufferedWriter(new File("myfile.txt")) { out =>
  out write "whatever"
  ...
}

Es könnte jedoch andere Möglichkeiten geben, die Verwendung von geschweiften Klammern zu unterstützen, ohne mehrere Parameterlisten zu haben.

Eine verwandte Frage: Warum wird in Scala die Verwendung mehrerer Parameterlisten als "currying" bezeichnet? Gewöhnlich wird Currying als eine Technik definiert, um eine n-ary-Funktion zum Unterstützen einer teilweisen Anwendung unförmig zu machen. In Scala kann man jedoch teilweise eine Funktion anwenden, ohne eine "curried" Version (mehrere Parameterlisten mit jeweils einem Parameter) der Funktion zu erstellen.


75
2018-01-13 19:12


Ursprung


Antworten:


Es ermöglicht Ihnen, z.

scala> def foo(as: Int*)(bs: Int*)(cs: Int*) = as.sum * bs.sum * cs.sum
foo: (as: Int*)(bs: Int*)(cs: Int*)Int

scala> foo(1, 2, 3)(4, 5, 6, 7, 9)(10, 11)
res7: Int = 3906

76
2018-01-13 19:55



Sie können nicht nur Methoden schreiben, die wie Teile der Sprache aussehen (die Sie bereits entdeckt haben), sondern auch, dass der Typ-Inferferenzblock jeweils mit einem Block arbeitet.

Also in diesem:

def foo[T](a: T, b: T)(op: (T,T)=>T) = op(a,b)
foo(1,2){_+_}

T wird zunächst als abgeleitet Int, die dann als Typ der beiden Unterstriche im Verschluss verwendet wird. So weiß der Compiler bei vollständiger Typsicherheit, dass die Operation + gültig ist.


45
2018-01-14 00:36



Um Ihre "verwandte Frage" zu beantworten, ist currying einfach eine Möglichkeit, eine Funktion aus mehreren Argumenten zu machen (A, B, C) => Din eine Funktion, die ein Argument annimmt und eine Funktion, z. A => (B => (C => D)) (Klammern gezeigt, aber nicht notwendig).

Die tupelisierte Form und die Curryform sind isomorph, und wir können frei zwischen ihnen übersetzen. Alle diese sind gleichwertig, haben aber unterschiedliche syntaktische Implikationen:

(A, B, C, D, E) => F
((A, B), (C, D, E)) => F
(A, B) => (C, D, E) => F

Wenn Sie separate Parametergruppen deklarieren, ist dies die Art von Curry, die Sie gerade ausführen. Die Multiparametergruppenmethode ist eine Methode, die eine Funktion zurückgibt ... Sie können dies in der REPL sehen:

scala> def foo(a:Int, b:Int)(c:Int, d:Int, e:Int):Int = 9
foo: (a: Int,b: Int)(c: Int,d: Int,e: Int)Int

scala> foo _                                             
res4: (Int, Int) => (Int, Int, Int) => Int = <function2>

24
2018-01-13 21:36



Rückverweise in Standardargumenten:

case class Foo(bar: Int)

def test(f: Foo)(i: Int = f.bar) = i*i

test(Foo(3))()

20
2018-02-27 20:22



Ich kenne eine der Motivationen implizite Parameterlisten. "implizit" ist eine Eigenschaft der Liste, nicht der Parameter. Eine andere war wahrscheinlich Fallklassen: Nur die erste Parameterliste wird zu Fallfeldern.


12
2018-01-14 05:36