2011-06-11
ここがヘンだよScala言語
Scalaを触ったり言語仕様を眺めた上で、ストレスを感じたものをいくつか挙げる。おそらくコミュニティでの議論は既に終了しているであろうし、無意味な作業に感じられて仕方がないが、某所でまとめると言ってしまったので、我慢して進める。
突撃されると面倒なので一応述べておくが、別にScalaがダメだとか、Scalaが使えないとか言いたいわけではない。この程度の訓練は必要なのだ、ということだ。
追記
びっくりするほどのバカだと思われている節があるが、ScalaやJavaの思想を知った上で、あえて記述している部分も多分にある。一応。
捉え違いしている部分や、Scala的な考え方が知りたい方は、コメントをご覧になるのが良いでしょう。
if式の返り値
val v1 = if (1 < 2) {"a"} println(v1) val v2 = if (1 < 2) {"a"} else {"b"} println(v2)
v1はUnit、v2は"a"。else節が無い場合、「最後に評価された式を、返り値とする」というルールから外れる。
2.8.1、2.9.0等、現行の版では、v1、v2ともに"a"が返る。ルール通りの動きで問題はない。
除外インポート
import scala.collection.mutable.{_, Map => _, Set => _}
サンプルはMap、Set以外の全クラスをインポート。ここで、"_"にワイルドカードとしての役割と、消去の役割をもたせている。こんなのよく通したな。
typeと別名インポート
typeがあるなら別名インポートはいらないのでは?
forのネスト
for(i <- 0 to 10; j <- 0 to 10; k <- 0 to 10) { print(i + ":" + j + ":"+ k) }
ループが一つなのか、三つなのか、ぱっと見で分からない。必要だったのか?
for内包表記中のifとif式
for(n <- List(1,2,3,4,5) if n % 2 == 1) yield print(n + " ") // OK val n = 3 val = if n % 2 == 1 // コンパイルエラー }
内包表記中のifと、if式は違う。
forとforEach
クロージャとforEachメソッドをサポートするなら、for式は必要ないのでは?
yieldは好みじゃない。特例だから。
タプルのインデックス
overrideの有無
どちらかにして欲しい。
インスタンス生成の責務
わざわざクラスのオブジェクトとしての振る舞いをobjectに括りだしたのだから、インスタンス生成の責務はobjectに渡せば良かったのでは?
インスタンス生成時のnewの有無
class, caseクラス、object。場合によってnewを付けたり、外したり。
コンストラクタ
基本コンストラクタと、thisを用いて定義するコンストラクタ。分ける必要があったのか?
プレースホルダ
"ACBED".sortWith(_ > _)
複数の引数を取る場合、異なるオブジェクトに同じ名前を付けることになり、順番に依存する。
Mutatorの定義
class Foo { var bar: Int = _ def bar_=(value: Int) { this.doSomething this.bar = value } }
特別なメソッドの書き方。
似ているキーワード
None、Nothing、Null、null、Nil。一つ一つ意味と用法を覚える。
mutableなSet,Mapと、immutableなSet,Map
性質の異なるものを、わざわざ同名にする必要はあったのか?
コロンで右結合
通常の左結合の演算子が混じると面倒。
パラメータ境界
foo[A <: T]、bar[A >: T]、boo[A <% T]。このときコロンで右結合は関係あるんだろうか?
UML的なsuper-subの矢印の方向とも逆なので、Scala用の解釈として覚える。
パーサーやらの都合は知らないが、foo[ A.isSubtypeOf[T] ]、bar[ A.isSupertypeOf[T] ]、とかのほうが読み下すには良いと思う。
暗黙の型変換
implicitにやるよりは、必要になった時点でtoString()のようなフレームワークで指定したconverterメソッドを呼び出す方が好み。言語機能に同じような役割の新要素を追加するよりマシ。
notメソッド
unless文をサポートしないなら、Booleanにnotメソッドくらいは装備しておいて欲しい。
コンパニオンの参照
class A { def companion = A // 名前を直に指定するのはカッコ悪い def foo = this.companion.defaultValue } object A { val defaultValue = 10 }
コンパニオンを取得するメソッドくらい装備しておいて欲しい。
unsignedがない
32ビットunsignedなら、4ByteをByteでとってLongに変換。低いレイヤやネットワーク関連で面倒な思いをしている人も多いことだろう。
おわり
キリがなく、面倒なのでやめる。触れたのは氷山の一角だ。省略可能な部分、型周辺、アノテーション周辺、"/:"や":\"などの演算子周りには、おそらく気持ちの悪い部分がゴロゴロ転がっている。
一貫性から外れ、特例を知らなければならない件が散見される。そもそも覚えるべきことが多い。現状、Scalaはそこそこ覚悟のいる環境だと思う。
『「訓練されたScalaプログラマ」には複雑さは見えないんじゃないか』というまつもと氏の言には大いに同意する。まぁ慣れれば助数詞のように気にならなくなるのだろう。
- 作者: Dean Wampler,Alex Payne,株式会社オージス総研オブジェクトの広場編集部
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/01/20
- メディア: 大型本
- 購入: 2人 クリック: 166回
- この商品を含むブログ (27件) を見る
- 106 http://twitter.com/
- 32 http://b.hatena.ne.jp/hotentry/it
- 25 http://reader.livedoor.com/reader/
- 20 http://b.hatena.ne.jp/entrylist/it
- 20 http://longurl.org
- 18 http://b.hatena.ne.jp/
- 15 http://b.hatena.ne.jp/entrylist
- 15 http://www.ig.gmodules.com/gadgets/ifr?exp_rpc_js=1&exp_track_js=1&url=http://www.hatena.ne.jp/tools/gadget/bookmark/bookmark_gadget.xml&container=ig&view=default&lang=ja&country=JP&sanitize=0&v=298d279074e4cc94&parent=http://www.google.co.j
- 9 http://b.hatena.ne.jp/entry/d.hatena.ne.jp/kaminami/20110611/p1
- 9 http://bit.ly/jBL3Zj