kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

FantomのImplicit CastsとOnionの黒歴史(にしたい)自動ダウンキャスト

Onionには以前自動ダウンキャストという今となっては黒歴史にしたい機能が入っていたことがあった*1。どういう機能かというと、たとえば、Object型の変数oをダウンキャストしてString型の変数sに入れたいとする。Javaだと以下のような感じだ。

Object o = ...;
String s = (String)o;

以前のOnionでは、このような場合、以下のように書くことで、処理系が自動的にダウンキャストを挿入してくれていた。

o: Object = ...;
s : String = o; //明示的なキャストを省ける!

ジェネリクスが無いOnionで少しでも利便性を上げようとして導入した機能だったが*2、変数の代入時に発動するだけならともかく、メソッド呼び出し時の引数渡しでも発動するようにしようと考えると、関数のオーバーローディング規則が無意味に複雑化する&直感的でない動作になる事に気づいて、結局Onionからは削除したという経緯がある。だが、先ほどFantom Programming Languageのドキュメントを改めて眺めていたら、どうもFantomにその機能があるらしい事に気づいた。FantomではImplicits Castと呼んでいるらしいが、やっていることはほとんど同じである。以下、Fantomのドキュメントから引用する:

For example:

Int func(Int x) { ... }

Int i := 5
Num n := 5
Str s := "foo"

// statically correct as is: Int.fits(Int)
func(i)  =>  func(i)

// implicit cast inserted: Int.fits(Num)
func(n)  =>  func((Int)n)

// compile time error: !Int.fits(Str)
func(s)  =>  error
http://fantom.org/doc/docLang/TypeSystem.html

Onionではオーバーロード規則がやたら複雑化するために、メソッド呼び出し時の引数渡しに伴う自動キャストまでは実装しなかったのだが、Fantomではそれも実装されてしまっている!Fantomではメソッドオーバーローディングが存在しないため、これを実装してしまっても問題無いということなんだろうか。この言語の作者に妙に親近感を覚えてしまった。まあ、Fantomの方がずっとちゃんと処理系が作られているし、Onionなんかと比較するのは失礼かもしれんけど。

*1:SourceForge.jpからリリースされているビルドの最新版には今も入っているが、リポジトリの最新版では削除されている

*2:確か、G言語(まともなドキュメントが残ってないが、現在は[http://en.wikipedia.org/wiki/Deesel:title=Deesel]?)の仕様を見て取り入れたんだったと記憶している