かとじゅんの技術日誌

技術の話をするところ

Scalaのカリー化について学ぶ

Scalaでカリー化。「カリーか」って聞くと、あれしか想像できなかったのですが、なんとなく理解したというエントリ。

まず、このエントリを読む。
Scalaの関数部分適用とカリー化 - kyabの日記

関数型プログラミングの世界は奇妙な世界ですね。慣れてくると好きになるわけで。ジョジョに似てますねー。。いや、なんでもないです。

関数の部分適用ってどういう時に使えるのかな?って感じですが、カリー化は無名関数を渡す使い方は、リソース開放のために使えますね。それが下記の例。
scala勉強会第3回のことなど - scalaとか・・・から、

object Utility{

  /** C#のusing文のパクリ
   * @tparam A closeという名前を持っているものならなんでも
   * @tparam B 2番目の引数の関数オブジェクトの戻り値の型(これもなんでもいい)
   * @param resource 最後にcloseを必ず呼ばないといけないオブジェクト 
   * @param func 1つめの引数のオブジェクトを使用して行う処理
   */
  def using[A <: {def close()},B](resource:A)(func:A => B):Unit = {
    try{
      func(resource)  //処理実行
    }catch{
      case e:Exception => e.printStackTrace  //エラーキャッチしたら、とりあえずログはいておく。(本当はこの部分の処理とか変える必要あるはず)
    }finally{
      if(resource != null) resource.close()  //エラーが起きても起きなくても、必ず最後にcloseを呼ぶ(close呼ぶことによって、さらに例外が発生するようなものの場合、さらに何らかの処理が必要ですが・・・(´・ω・`) )
    }
  }
}

C#でコード書くときはusingは普通に使うわけですが、Scalaではカリー化を使うと同じことができるわけです。まさに言語を拡張している気分。。
さらに型引数の

A <: {def close()}

の部分は、Scalaの静的型付けのダックタイピング?みたいなところがイケてますね。Aのcloseメソッドのシグニチャのみを指定できるという。Javaでは、Closeable#closeメソッドを使うことを想像するけど、Closeableの実装しかcloseできないということになるので、いろいろ姑息なことをしなくてはならん。例えばこんな感じ。
http://sourceforge.jp/projects/sisioh/svn/view/altair/non-bundle/sisioh-commons/trunk/src/main/java/org/sisioh/commons/utils/CloseableUtil.java?view=markup&root=sisioh

usingを呼び出す時は型引数を明示的に指定しなくても、型推論するらしい。これはいい。
scala勉強会第3回のことなど - scalaとか・・・から、

import Utility.using //例として、自分で定義したものをimport

object JavaLikeDatabaseSelect {
  def main(args: Array[String]) = {
    Class.forName("org.postgresql.Driver")
    
    using(DriverManager.getConnection( "jdbc:postgresql://localhost/scaladb", "scalar", "scalar")){ 
      db =>
      val st = db.createStatement
      val sql = "SELECT id, name FROM sample"
      val res = st.executeQuery(sql)

      while(res.next){
        val id = res.getInt(1)
        val name = res.getString(2)
        println(id+", "+name)
      }
    }
  }
}

ScalaのIDEがブレイクスルーする前に、Scalaを扱えるようになっておこう。