Scalaはコンストラクタもカリー化できる!の続き
前回記事の続きです。
scalaはコンストラクタもカリー化できる! - rabitarochanの日記
ブログへのコメントや、Twitterのリプライでいろいろ教えていただきました。
@xuwei_kさん、@kmizuさん、ありがとうございました!
一部の引数を指定したコンストラクタ
一部の引数を指定したコンストラクタについては、前回失敗した書き方を少し変えることで可能でした。
scala> class Person(val name: String)(val age: Int) defined class Person // 失敗・・・ scala> val p1 = new Person("rabitarochan") _ <console>:8: error: missing arguments for constructor Person in class Person val p1 = new Person("rabitarochan") _ ^ // 成功!!! scala> val p2 = new Person("rabitarochan")(_) p2: Int => Person = <function1>
_ と (_) って何が違うの!?という疑問については前回記事のコメントか、@kmizuさんのブログ、
_ と _ の違い - ((プログラミング | 形式) 言語) について書く日記
にかかれてます。
case class の場合
例では普通のクラスを利用していましたが、case class を利用した場合は、以下のとおりにインスタンス化できます。
scala> case class Person(name: String)(age: Int) defined class Person scala> val p1 = Person("rabitarochan") _ p1: Int => Person = <function1>
case class を定義すると、コンパニオンオブジェクトも自動的に定義されます。
この場合、コンパニオンオブジェクトの apply メソッドに対して部分適用された関数が返ります。
手動でコンパニオンオブジェクトを定義した場合でも、同じ動きを確認できました。
// コンパニオンオブジェクトの定義は :paste してから。 scala> :paste // Entering paste mode (ctrl-D to finish) class Person(val name: String)(val age: Int) object Person { def apply(name: String)(age: Int) = new Person(name)(age) } // Exiting paste mode, now interpreting. defined class Person defined module Person scala> val p1 = Person("rabitarochan") _ p1: Int => Person = <function1>
まとめ
new Hoge("hoge")(_) と記述することで、カリー化したコンストラクタについても、部分適用(というの??)した関数を取得することができました。カリー化した場合の制限だと思っていたものも解決しました。
あとは、@kmizuさんのブログを読んで理解するだけです。
言語仕様も読まないとなぁ・・・。