2009/11/12
プログラミング言語Goの第一印象
C言語が好きです。「 パーフェクトJava 」を執筆しておいてなんですが、実はJavaよりCが好きです。誤解のないように書いておくとJavaとCのどちらが良い言語かと聞かれればJavaと答えます。でも、好き嫌いと良い悪いの評価は別です。
だからケン・トンプソンは神様のひとりです。そんなわけで プログラミング言語Go を見てみました。誤解のないように書きますが、Googleだから見たわけではありません、ケン・トンプソンだから見ました。
以下、Goの第一印象です。
Debianのx86環境でGoが動きませんでした。Goコンパイラは生成できたのですが、Goのコンパイルが失敗します。動かして確認していなので、間違いがあるかもしれません。
良さそうなこと:
- 関数やメソッドが複数値を返せること
- いきなり話が小さいですが、CやJavaに常々欲しいと思う言語機能です(構文の問題がありますが)。これでバグが減るわけではありませんが、Cで値結果引数を使ったり、Javaで値を返すだけのバリューオブジェクトクラスを書くたびに悲しい気分になります。複数の値を返せれば、これらの小さなストレスから開放されます。
- stringが組み込み型であること
- stringの内部コードはUTF-8です。ぼくは 内部コードUTF-8賛成派 なのでこの決定は指示します。stringはimmutable(文字の書き換え不可)かつunmodifiable(サイズ変更不可)です。JavaのStringクラスと同じです。これはこれでいいと思っていますが、変更可能な文字列が欲しい場合は自分でbyteの配列を作って(後述するように組み込み型のarrayはunmodifiableなので)自前で動的配列の実装を書け、ということでしょうか。中途半端に感じます。変更可能文字列も組み込み型に提供してくれればいいのにと思います(追記。container/vectorライブラリにstringvectorがありました)。
- mapが組み込み型であること
- mapが組み込み型です。組み込み型にすることでmapが配列と同じシンタックス(添字に数字以外を使えるのがmap)で扱えます。もちろん、演算子オーバーロードがあれば組み込み型にしなくても、同じシンタックスの実現は可能です。Goは演算子オーバーロードを持ちません。プログラミング言語ミニマリズム(=言語のコア機能は小さければ小さいほど良いと考える思想)に則れば演算子オーバーロードの方が好ましい解です。ぼく自身はどちらかと言えばミニマリストですが、演算子オーバーロードは嫌いなので(好き嫌いと良い悪いは別です)、map組み込み型支持です。
- defer構文
- 関数またはメソッドが抜ける時に必ず呼ばれる処理を書けます。要は関数単位でのfinally相当の言語機能です。Cにあったらあったで便利かもしれませんが、無くても困りません。
嫌なこと:
- 全然、Cと似ていないこと
- GoがCに似ていると言っている人がいたら、どこが?、と聞きたくなります。中括弧の代わりにbegin、endだったらPascalと見誤るぐらいです。Pascalは好きではありません。
- 型を後ろに書くこと
- Pascal風、あるいは(型指定も書けるようになる)次期JavaScript風。慣れの問題かもしれませんが型が変数の後ろにあるのが気持ち悪いです。(追記。3時間見ていたら慣れてきました。人間は適応するものです)
どうでもいいこと:
- while文とdo-while文がないこと
- ループ構文はfor文だけのようです。どうでもいいです。
- switch-caseのデフォルト動作がfallthroughではないこと(予約語fallthroughがあること)
- caseが次のcaseにスルーせずに抜けます。文法的にはcaseラベルからcase節扱いになっていますが、正直、どうでもいいです。スルーさせたい場合は予約語fallthroughを書きます(CやJavaで、抜けたい場合にbreakを書いていたのと逆になります)。
- 例外がないこと
- FAQによればいずれ入るかも、とのことですが、どうでもいいです。
- 先頭が大文字の名前はパッケージの外に見えること
- どうでもいいです。
微妙なこと:
- クラスがないこと
- どこからコードを書き始めればいいのかと途方に暮れる程Java脳に毒されてはいませんが、クラスを持たないという決定は大胆です。
- 配列やオブジェクトをスタック上に確保できること(?)
- Javaをやっていてしばしば欲しいと思うのが、オブジェクトをスタック上に確保することです。あるメソッド内だけで使うオブジェクトがある時、いちいちヒープに確保すると思うと悲しくなります。スタックに確保できれば、メモリ確保も破棄もオーバーヘッドゼロです。GCにも負荷をかけません。これができるGoには諸手を挙げて賛成、と言いたいところですが、次に続きます。(追記。と思ったら、ローカル変数のアドレスをreturnしているサンプルコードがあるので、ここに書いたことは嘘かもしれません。あるいはローカル変数のアドレスを返した場合だけ、クロージャ扱いにしてスタック状態を退避させているのかもしれません)
- ポインタ演算がないのにポインタ型があること
- ポインタ演算がないのになぜかポインタ型があります。なんでかなと思いましたが、理由のひとつは、上記のスタック上に確保したオブジェクトの参照渡しを実現するためのようです。値渡しの関数呼び出しの下で参照渡しを実現するには、1.C++のように参照型を用意する。2.Javaのように思い切ってオブジェクトを代入可能な変数は全部(暗黙に)参照型にする。3.CやGoのようにアドレス演算子(&)とポインタ型を定義してポインタ値を渡す。の3パターンあります。個人的には、ポインタ型もアドレス演算子も嫌いではありませんが、ポインタ演算がないなら、Javaのように全部参照型でいいじゃないかと思います。誰も困っていないですし。ちなみにメンバー参照の演算子は、左オペランドがポインタ型でも.(ドット演算子)です。->(矢印演算子)はありません。channel用に逆向き演算子(<-)はありますが、別の意味です。
- ジェネリック型がないこと
- FAQによればいずれ入るかも、とのことです。ジェネリック型がないことは非難が集中しそうです。Goソースツリー内のテストコードにstack.goというスタックの実装例があります。要素がint専用のスタックの実装になっています。(Cのように)void*とキャスト使ってください、と開き直ったらそれはそれでぼくは構いませんが、たぶんそんな開き直りはしないと思います。(Cのように)プリプロセッサマクロの黒魔術も使えませんし、どうするのでしょう。Java1.4のように要素の基底型をインターフェースで定義しろ、になるのでしょうか。(追記。ライブラリのvector.goを見たらこんな感じでした)
- arrayがunmodifiable(サイズ固定)であること
- arrayが固定長であること自体は(CでもJavaでも同じなので)別にいいのですが、arrayを組み込み型に持つなら、動的配列も組み込み型で提供してくれれば良かったのにと思います。(container/vectorライブラリにvectorがありました。当然、組み込み型とはシンタックスが異なります)。
- インターフェースが微妙なこと
- インターフェースという名称からJavaのインターフェースと同じかと思いましたが、見た目は全然違います。目的は振る舞いの継承なのでJavaと同じですが。使い方は http://golang.org/doc/go_for_cpp_programmers.html#Interfaces を見てください。呼ぶ側の視点では、インターフェース型の変数を使った場合、仮想関数の呼び出しで、そうでない場合はスタティックな呼び出しになります。C++の予約語virtualよりはマシですが、個人的には、すべて仮想関数呼び出しになるJavaスタイルでもいいと思っているので微妙です。Javaのように予約語implementsで型の継承関係を明示できる方が好ましいと思うのはJava脳に侵されているためでしょうか。
- typeはtypedefと違うこと
- type Counter intは、Cのtypedef int Counterのように見えますが、型を作っていることが異なります。type Counter intのCounter型には(インターフェースを継承した)メソッドを定義できます。言語オタクなら大喜びしそうな機能ですが、ぼくは言語オタクではないので、そんなに感動しません(type Counter struct { count int } で充分です。ごめんなさい)。
- goroutineとchannel
- Goのセールスポイントのひとつです。言語機能としてスレッド処理を持つことに異論はありませんが、微妙なことに分類した理由は、並行処理の本質的な難しさがなくなるわけではないだろう、という達観のためです。channelはまだきちんと見ていません。
日本語情報:
usamimiさんがGoのメーリングリストを作ったようです。Goに興味がある人は参加するとよいと思います。
- Category(s)
- カテゴリなし
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/inoue/golang/tbping
Re:プログラミング言語Goの第一印象
これの謎は解けました。下記参照。
http://dev.ariel-networks.com/Members/inoue/go-allocation