Scala-tutorial.pdf
みずしまさん作成のScala-tutorial.pdf資料を見たがよくまとまっており非常に分かりやすい。しかし、ScalaはJava、Ruby、関数言語(Haskell、OCamlなど)が好きな人は親近感を覚える言語ではないかと思った。C++、Pythonが好きな人は毛色が違う言語である気がした。
「高階関数(3)」のopen関数の例で、引数の()が2つあるのはどういう意味になるのだろう?foo(a :Int)が、(Int => Int)型の関数を返すのだろうか?
scala> def foo(a :Int)(b :Int) = {a + b} foo: (Int)(Int)Int scala> def bar(a :Int, b :Int) = {a + b} bar: (Int,Int)Int scala> foo(1)(2) res0: Int = 3 scala> bar(1, 2) res1: Int = 3
ここで、bar(1)と呼び出すと引数の個数が不足しているので、Haskellのように自動的にカリー化されずエラーが発生する。ここでのfooはfoo(1)(2)のように呼び出し、barはbar(1, 2)のように呼び出すので同じものを表している訳ではない。()と,を省略した、foo 1 2もエラーだし、bar 1 2もエラーとなる。つまり、fooとbarを同様に扱えない。同様に扱うにはどうすれば良いのだろう?
Haskellでは以下のように関数呼び出しの()を省略可能で、しかも自動的にカリー化されるので、上記のfooとbarのような区別はないと思われる。
foo a b = a + b bar = foo 1 main = print $ bar 2 --実行結果 3
追記(2008/5/13):
みずしまさんにコメントで教えて頂いたので整理。
// Haskell // foo :: a -> a -> a // foo a b = a + b // Scala // (Int) => (Int) => Int def foo(a :Int)(b :Int) = a + b
// Haskell // bar :: (a, a) -> a // bar (a, b) = a + b // Scala // (Int, Int) => Int def bar(a :Int, b :Int) = a + b
// Haskell // foo a b = a + b // foo2 = foo 1 // print $ foo2 2 // Scala val foo2 = foo (1) _ println(foo2(2))
Scalaの方は構文に癖があるけど、それなりの理由があるはず。とりあえずScalaは、引数で与える個数を間違えた場合はエラーが出てくれるので安全かも。