2011-01-13 4 views
71

複数のパラメータリスト。 def foo(a:Int)(b:Int) = {}と複数のパラメータ(リストあたり)。 def foo(a:Int, b:Int) = {}は私が知る限り、意味的に同等であり、ほとんどの関数型言語は複数のパラメータを宣言する方法が1つしかありません。 F#。Scalaは複数のパラメータリストと複数のパラメータをリストごとに提供するのはなぜですか?

これらの両方のスタイルの関数定義をサポートするために私が理解できる唯一の理由は、1つのパラメータしか持たないパラメータリストを使用して構文に似た言語拡張を許可することです。

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

は今の構文に見える

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

で呼び出すことができますが、複数のパラメータリストを持つことなく、中括弧の使用をサポートする他の方法があるかもしれません。

関連する質問Scalaの複数のパラメータリストを「カリング」と呼ぶのはなぜですか?カリングは、通常、部分的なアプリケーションをサポートするために、n進関数を単項式にするためのテクニックとして定義されます。しかし、Scalaでは、関数の "カレー化"(それぞれ1つのパラメータを持つ複数のパラメータリスト)を作成することなく、部分的に関数を適用できます。

+0

:それは単に、より数学的に表現力です。あなたが複数に一般化できるときに1つのリストで十分である理由:) – matanster

答えて

75

それは例えばを行うことが、あなたができるようになり:

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 
+2

これの1つの制限は、各パラメータグループに対して可変長であるが、グループの数は固定されなければならない(この場合、3である)。 –

+25

この回答を承認したので、これは単なる例であり、あなたの「なぜ」の質問に対する標準的な答えではないかもしれないことに注意してください。 –

+1

これは、両方の種類のパラメータを持っているためにこれまでに見た最初の具体的な理由です。他はすべて非常に特別です。それでも、私は文法的な手荷物と言語の複雑さに値するものとして、これらの理由のいずれも見ていない。 –

23

あなたに答えるために、「関連する質問を、」カリー化は、単純に1を取る関数に、たとえば(A, B, C) => Dのために、複数の引数の機能をオンにする方法です引数をとり、関数を返します。 A => (B => (C => D))(括弧が表示されていますが、必要はありません)。

タプル化されたフォームとカレー化されたフォームは同形であり、それらの間で自由に翻訳できます。これらのすべてが同等であるが、異なる構文上の意味合いを持っている:あなたは別のパラメータグループを宣言すると、これはあなたがやっているカリー化の種類

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

です。マルチパラメータグループメソッドは関数を返すメソッドです...あなたはREPLでこれを見ることができます:

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

としてだけでなく、あなたが言語の一部のように見える方法を記述することができます(これを使用すでに発見されています)、タイプ推論は一度に1つのブロックで動作することに注目する価値があります。この中のSO

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

Tは、まず閉鎖中の2つの下線のタイプとして使用される、Intように推測されるであろう。 これはコンパイラが完全な型の安全性を持って+演算が有効であることを知る方法です。

12

私は、暗黙のパラメータリストが動機の一つであることを知っています。 「暗黙的」は、パラメータではなくリストのプロパティです。別のケースはおそらくケースクラスです。最初のパラメータリストだけがケースフィールドになります。デフォルト引数で

+0

あなたはこれを拡張することができますか? –

+1

チャンスがないようです... – zapadlo

+0

複数のパラメータリストを持つケースクラスについては、[このバグに関するコメント](https://issues.scala-lang.org/browse/SI-5009)を参照してください。それが、私がこの機能について最初に聞いたところです。 – ebruchez

18

後方参照:一般的に

case class Foo(bar: Int) 

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

test(Foo(3))() 
関連する問題