Re: Re: 不満の記録

ref: http://d.hatena.ne.jp/kmizushima/20090615/1245002849

またまたみずしまさんにいろいろ教えてもらいました。ありがとうございます。

束縛前の val 変数を参照できてしまった。かなりはまった。これは Scala のバグと言っていいと思う *1 。どう直すかというとなかなか難しいけれど。

仕様かどうかという意味でなら、これはバグではなく、(少なくとも現在のScalaにおいては)仕様通りの挙動です(仕様のバグじゃないの?という話はあると思いますが)。

仕様のバグという意味でした。実装のバグなんて、言語の評価とは独立ですよね (ぉ

-Xcheckinitオプションを使うのが良いかと思います。

これは動的に検査するんですね。うーん。。この手のバグが疑わしいとわかってるときには便利ですね。というか、開発時には常につけておけばいいのか。-deprecation とか -unchecked とか、デフォルトでオンにしといてほしいオプションが多いですね。

引用元のコードを意図通りに動作させたい場合、lazy valで初期化を遅延させると良いです。

どうにでも対処はできることはわかるんですが、そもそもこんなバグの元な参照がコンパイラを素通りするとは夢にも思わなかったのでした。が、これを静的に検査するのは open research problem だとか intractable だとかいわれてますね。単純に前方で定義されている識別子を参照禁止にするのは Java の人たち的に嫌ってことかな。まあ let rec ... and ... みたいな構文が必要になるのは嫌か。
コンパイルが通れば、ぬるぽのようなしょうもないバグはないぜ!」という、OCamlHaskell のような堅牢性は期待しない方がよさそうですね。

空行があるかないかで意味が変わって、はまった。

このコードだと、どちらの場合もコンパイルエラーになるはずです。

ああ、その通りです。すみません。

list.foreach
{x =>
}

みたいなのを許したかったのではないかと。

きっとそうだろうとは思うんですが、次の行に続くかどうかのルールが例外的でわかりにくいんですよね。常に続く (改行を無視する) わけではないけれど、続かないとして解釈可能な場合でも続くこともある、というあたりが中途半端で。

val で複数の変数が定義しにくい。

個人的にはコンパイラが多少頑張って、上記のようなタプルパターンを使った代入を最適化してくれる方向が望ましいのかなと思っています。

そうだと思います。Ruby の多重代入では最適化されてます (YARV では) 。

val x, y, z = 1で何が嬉しいのかという点ですが、(snip) たとえば、scala.Enumerationがいい例になっています。

ああーなるほど! 右辺は変数の数だけ評価されるんですね。この見た目でそんな風に動くとは全く想像できませんでした。

配列リテラルやリストリテラルでいちいち Array や List と打たなきゃいけない。xml リテラルなんぞ入れる前に必要なリテラルがあるだろう。

以下のように適当な1文字の別名付けるとか、やりようはあるので、あんまり気にならないですが。

うーん。これを毎回やるかと考えると、正直あんまり気が進まないです。

あと、Scalaの場合、標準のコレクションの種類がかなり豊富なので、ArrayとListだけ特別扱いとかしても、他のコレクション(例えばSet)にリテラルが使えないのでは、あんまり嬉しく無いというのもあります。

なるほど。大クラス主義じゃないとなかなか難しいですね。しかし XML なあ……ユーザ層の違いだろうなあ。

パターンマッチが型安全じゃない。

ご想像の通り、JavaVMの仕様のせい(正確には、Genericsの実装に基づく制限)で、(snip)

ですよねー。

ただ、case x:Type形式の、型にマッチするパターン(かつ、TypeがGeneric型)さえ使わなければ基本的に安全なので、実用上注意しなければならない箇所は多く無いと思います。

実用上あまり問題ないのはわかるんですが、それでも、型安全性を失うような問題を抱える機能は黒魔術扱いすべきだと思ったのでした (普通には使えないようにするなどして) 。この手の堅牢性を重視してないと言われればしょうがないのですが。
そういえば catch の中が型にマッチするパターンなので悩ましいですね。

便利メソッドがなさすぎて息苦しい。

sortはscala.util.Sorting(object)に、

これは見つけてたんですが、ちょっと見て比較関数が指定できなくて使えねーと思って投げたんですが、stableSort なら指定できますね。

flattenはscala.List(型じゃなくてobjectの方)に、そのまんまのがあります。

これは見つけられてませんでした。

可変長配列に関しては、scala.collection.mutable.ArrayBufferか、scala.collection.mutable.ListBufferを使うのが基本になるかと思います。

これも見つけられてませんでした。今度使ってみます。だいぶ息が楽になりそうです。


つまるところ、ぼくが Scala に期待していたのは

  • Ruby のような快適さ (書きやすい文法に豊富な便利メソッドなど)
  • OCaml/Haskell のような堅牢性 (主に型安全性; 型推論が弱いのはともかく)
  • 速さ

だったんですが、どうやら堅牢性のところは大分いい加減に扱われているんだなあ、というのが現時点の印象です。