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)
}
}
}
}