SSブログ

Scala で 20.minutes.ago [Scala]

Ruby で整数型にメソッドを付け足したりすると 20.minutes.ago みたいな書き方ができるけど C# 3.0 でもそういうことができるようになるという話 [1] [2] [3] を読んだ。

Scala だと既存クラスを拡張するという形ではなく暗黙の型変換 (View) を定義してあげることによって同じことができる。

scala> import java.util._
import java.util._

scala> class TimeSpan(n:long) { def ago = { new Date((new Date).getTime - n) } }
defined class TimeSpan

scala> class ExtendedInt(n:int) { def minutes = { new TimeSpan(n * 1000 * 60) } }
defined class ExtendedInt

scala> implicit def int2eint(n:int):ExtendedInt = { new ExtendedInt(n) }
int2eint: (int)ExtendedInt

scala> 20.minutes.ago
unnamed0: java.util.Date = Thu May 31 20:32:50 JST 2007

scala> new Date
unnamed1: java.util.Date = Thu May 31 20:52:53 JST 2007

仕組みはこうだ。整数型には minutes というメソッドはないので Scala コンパイラは整数型を minutes メソッドを持つ型に変換できないかと思って暗黙の型変換メソッドを検索する。そこで int2eint というメソッドを見つけてこれを使って ExtendedInt に変換し、その ExtendedInt 型のオブジェクトの minutes メソッドを呼ぶようにする。このメソッドは TimeSpan 型のオブジェクトを作って返す。以降は説明不要と思う。

ついでに Ruby らしい構文と思われる 3.times do ~ end みたいなものも同様にして作れる。

scala> class Loop(n:int) { def times(x:()=>Unit):Unit = {for (i <- 1 to n) x() } }
defined class Loop

scala> implicit def int2loop(n:int):Loop = { new Loop(n) }
int2loop: (int)Loop

scala> 3.times { () => Console.println("cheer"); }
cheer
cheer
cheer
unnamed0: Unit = ()

で、ここまで書いておいてなんだけど個人的には 20.minutes.ago とか 3.times みたいな書き方はまだあまり好きになれない。この感じを説明するのは難しいけど、「高度に自然言語に似せたコードは出鱈目と区別がつかない」とでもいうものだろうか。コードが「確かにこれでいい」という感じがつかめなくなる気がするのだ。慣れの問題かもしれないけど。

Ruby にしたってコードの大抵の部分は全然英語の構文通りじゃない見かけをしているわけで、そこにひょっこり 20.minutes.ago が出てきてもそんなにうれしいかなあと思う。短く書けるというだけならもっとプログラミング言語として無難な表現方法はありそうだし。

[1] http://haacked.com/archive/2007/05/24/ruby-like-syntax-in-c-3.0.aspx
[2] http://www.rubyist.net/~matz/20070526.html#p01
[3] http://haacked.com/archive/2007/05/28/the-only-universal-language-in-software-is-english.aspx


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。