ページ

2009年11月27日

Blacows

バージョン管理いろいろ

ソフトウェアの開発にバージョン管理はなくてはならないツールです。たとえ一人だけで開発しているとしても、バージョン管理システムを使わずに開発している人たちがいるとは信じられません。

バージョン管理システムはほんの10年ぐらい前まではCVSがデファクトでした。これさえ覚えておけば、大体何とかなりました。その後、アリエルでも使っているSubversionがはやり出しました。CVSはいろいろ不満点があったので、(新しいものに適応できない)開発部長の反対を押し切ってSubversionを使い始めました。

さらに、時代は流れて、今はMercurialだ、gitだ、といろいろあります。会社の中はSubversionでとりあえず問題(branchの開発にはちょっと・・・)ないので、多分、そのままです。自分の個人のコードはMercurialで管理しています。

でも、いろんな他の人が作ったライブラリとかは、Mercurialだったり、gitだったりで 、いろいろあります。他の人を見ていると、いろんなツールを使いこなしているみたいです。少なくとも僕にはそう見えます。すごいです。置いてきぼりにならないようにしないといけません。でも、見栄をはって、分かっているような顔をしています。

ついでに、やっぱり分散リポジトリは会社とかそういう組織では管理できる気がしません。 



2009年11月26日

ザクザクザク2

ザクザクザク

ラブモードジンジャー

golangからPythonの関数を呼び出してみる

前回の続きです。golangのコードからPythonの関数を呼び出してみました。とりあえず、Pythonのドキュメントのここに書いてあることができるようになりました。とりあえず、動くことを目標にしているので、わざとはっしょってたりしています。golangは簡単にCのコードを呼び出せるのはいいのですが、ほとんど考えることがないので、ラッパーを自動生成できないのかな?

ついでに、macroはいやーん、だと思っていましたが、
package "py"

/*
#import "myheader.h"

void wrapper_func(int v) { SOME_MACRO(v); }
*/
import "C"
みたいな感じにしておけば、使えるのか・・・。

で、今のコードはgithubにいます。こんな感じになります。




func setArgs(pArgs *py.Object, index int, value int) bool {
pValue := py.Int_FromLong(value);
if pValue == nil {
fmt.Printf("Value : %d\n", value);
py.Err_Print();
return false;
}
pArgs.Tuple_SetItem(index, pValue);
return true;
}

func runFunc(pythonfile string, funcname string, arg []int) {
fmt.Printf("--- runFunc ------------------------------\n");
pName := py.String_FromString(pythonfile);
pModule := py.Import_Import(pName);
fmt.Printf("import done \n");
pName.DecRef();
if pModule != nil {
fmt.Printf("pModule %t\n", pModule);
pFunc := pModule.GetAttrString(funcname);
if pFunc != nil && pFunc.Callable_Check() != 0 {
pArgs := py.Tuple_New(2);
if setArgs(pArgs, 0, arg[0]) == false {
pArgs.DecRef();
pModule.DecRef();
fmt.Printf("Cannot Convert Argument\n");
return;
}
if setArgs(pArgs, 1, arg[1]) == false {
pArgs.DecRef();
pModule.DecRef();
fmt.Printf("Cannot Convert Argument\n");
return;
}
pValue := pFunc.CallObject(pArgs);
pArgs.DecRef();
if pValue != nil {
fmt.Printf("Result of call: %d\n", pValue.Int_AsLong());
pValue.DecRef();
} else {
pFunc.DecRef();
pModule.DecRef();
py.Err_Print();
fmt.Printf("Call Failed\n");
}
} else {
if py.Err_Occurred() != nil {
py.Err_Print();
}
fmt.Printf("Cannot find function %s\n", funcname);
}
py.XDecRef(pFunc);
pModule.DecRef();
} else {
py.Err_Print();
fmt.Print("error\n\n");
}
fmt.Printf("--- runFunc done ---\n\n");
}


でも、こっちをみたほうがわかりやすい。

でわでわ

2009年11月25日

インフルエンザがやってきた

3連休はインフルエンザで始まりました。僕がかかったわけではなく、次男がインフルエンザになりました。彼は生まれて初めてのインフルエンザでしかも新型です。正確には金曜の朝、熱が38度弱ありましたが、ぴんぴんして元気です。普段が37度ぐらいなので、ちょっと高いぐらいです。食欲旺盛で、いつもと全く変わりません。夜寝ているときに熱がどんどんあがりますが、すやすや寝ています。朝起きると38度弱にもどっています。まだまだ元気です。

とりあえず、もう一度お医者さんに行くとインフルエンザでした。タミフルをもらって夕方には、37度ぐらいに戻っています。元気です。でも、他の人にうつすといけないので、家の中に閉じ込めないといけません。一週間閉じ込めないといけません。大変です。困りました。

家の中には2才のちびがいます。どうせインフルエンザになるなら、一緒にかかればもう一度休まなくてもいいので、うつらないかなー、 と思っていましたが、全然平気です。僕はマスクが嫌いなので、マスクとかしないのですが、やっぱりまだ、うつりません。

おとなりさんの子供もインフルエンザになったらしいですが、他の人には移らなかったようです。新型に限らず、インフルエンザはこわい病気なので注意したほうがいいのかもしれませんが・・・。 



2009年11月24日

golangからPythonをちょっとだけ使ってみる

やっぱりヘビが好きなので、golangでも使いたいなー、と言うことでPythonを呼び出せるようにちょっとだけしてみました。goでインタープリタを実装する時間もスキルも、モチベーションもないので、CPYthonを呼び出すだけです。半分cgoのお勉強です。

まず、Pythonのコードを呼び出すようなテストコードgopy.goを書きます。pyで始まるようなところが、Pythonのラッパーです。Macでしか動かないMakefileです。


package main

import (
"py";
"fmt";
)

func main() {
fmt.Print("init\n");
py.Initialize();
fmt.Print("init done\n");
result := py.Run_SimpleString("print 'hello'");
fmt.Printf("script done %d\n", result);
py.Finalize();
fmt.Print("finalize done\n");
}


次にPythonのラッパー。とりあえず、テスト用なのでPy_Initialize, Py_Finalyze, PyRun_SimpleStringをラップします。次のコードgopywrapper.goがそれ。この人からCのコードとgoのコードが作られます。最初の方のコメントの部分がCと仲良くするための魔法です。

package py
/*
#include
*/
import (
"C";
)

func Initialize() {
C.Py_Initialize();
}

func Run_SimpleString(script string) int {
return int(C.PyRun_SimpleStringFlags(C.CString(script), nil));
}

func Run_Simple

func Finalize() {
C.Py_Finalize();
}



あとは、Makefileを書くだけです。実はこの人を作るのが一番時間がかかったかも。なぜかは、うーん、typo。でMakefile。


include $(GOROOT)/src/Make.$(GOARCH)

TARG=py
CGOFILES=\
gopywrapper.go

CGO_LDFLAGS+=-lpython -u _PyMac_Error /Library/Frameworks/Python.framework/Versions/2.6/Python
CGO_CFLAGS=-I/usr/include/python2.6/ $(CGO_FLAGS)
CFLAGS=-I/usr/include/python2.6/

LDFLAGS=-u _PyMac_Error /Library/Frameworks/Python.framework/Versions/2.6/Python

include $(GOROOT)/src/Make.pkg

%: gopywrapper.o install %.go
$(GC) $*.go
$(LD) -o $@ $*.$O

gopywrapper.o: gopywrapper.c
gcc -fPIC -O2 -o gopywrapper.o -c gopywrapper.c

gopy: install gopy.go
$(GC) gopy.go
$(LD) -o $@ gopy.$O



これで、make gopyとやれば、gopyという実行ファイルができます。./gopyを実行すると、


init
init done
hello
script done 0
finalize done


めでたしめでたし。次はこのへんをできるように・・・。

2009年11月20日

golangのevalをちょっとだけ見てみた

先日、evalがあると驚いていたので、golangのevalをちょっとだけ見てみましたが、よく分かりません。基本的には、eval_test.goをみて書いてみました。
テストケースとかstmt_test.goを見ると関数とかも値として返してくれるのかなー、と期待しましたが、違うようです。よく分かりません。動作としてはコンパイルして、スレッドの中で実行しているような気配を漂わせていますが、めんどーになってちゃんとは追ってません。実行時にバイナリを書き換えるとかいうソフトを昔聞いたような気がしますが、実行ファイルが自分でコンパイルして何かを実行するってやっぱりおもしろい。
でも、evalで何ができるかは、よく分からないんです。



package main

import (
"exp/eval";
"log";
)

func main() {
srcs := []string{
"1",
"type hoge struct {s string};",
"a:=1;",
"a",
"func f1() {}",
"1,2",
};

for _, src := range srcs {
world := eval.NewWorld();
log.Stdout("[Code] " + src + "\n");
code, err := world.Compile(src);
if err != nil {
log.Stderr("[Err] " + err.String());
} else {
value, err := code.Run();
if err != nil {
log.Stderr("[Err] " + err.String());
} else if value != nil {
log.Stdout("[Out] " + value.String() + "\n");
} else {
log.Stdout("[Out] (value == nil)\n");
}
}
}
}


実行結果

2009/11/20 17:42:25 [Code] 1
2009/11/20 17:42:25 [Out] 1
2009/11/20 17:42:25 [Code] type hoge struct {s string};
2009/11/20 17:42:25 [Out] (value == nil)
2009/11/20 17:42:25 [Code] a:=1;
2009/11/20 17:42:25 [Out] (value == nil)
2009/11/20 17:42:25 [Code] a
2009/11/20 17:42:25 [Err] input:1:1: a: undefined
2009/11/20 17:42:25 [Code] func f1() {}
2009/11/20 17:42:25 [Out] (value == nil)
2009/11/20 17:42:25 [Code] 1,2
2009/11/20 17:42:25 [Err] input:1:1: only one expression allowed


それから、"[...]int{1,2}"とかを実行すると、[Err] input:1:1: *ast.CompositeLit expression node not implementedとなる。

アリエルは新入社員をとってもいいと言う噂

アリエルでバイトしている女子大生は、もう、就職活動しています。僕は夏頃就職活動(と言うほどのこともしていないけど)したような記憶があるので、今時の人たちは早いです。何かが間違っていると思わなくもないです。

さて、アリエルは正規のルート(どこかの就職用のサイトとか)を通しては 新入社員を募集していないです。多分、開発に関しては僕が反対するので当分はやらないでしょう。でも、アリエルのサイト上にある採用用のメールアドレスに直接履歴書を送れば、大丈夫です。正確に言えば、履歴書じゃなくって、自分が書いているブログのURLと名前と連絡先だけでいいです。自分をアピールするためのものも、必要ないです。ブログを読んで、その人は技術が好きか、プログラミングが好きかを見ます。それだけです。

強いて言えば、Javaしかやっていない人はポイントが低いです。Javaは悪くないのですが、母数が多すぎてフィルタしにくいからです。それから、Javaはスキルをはかるのには向いていない言語ということもあります。

メインとなる言語(これは、Javaでもいい)と、もう一つ、別の言語(文化が違えばもっといい)ができればなおいいです。

今だと、「Go勉強しています」でもいいし、「これからはErlangでしょ」でもいいし、「ScalaはJavaの上で動きますが、いいですよ」でもいいし。

結局、新入社員だろうと、中途だろうとちゃんとしたプログラマしかとならいです。で、twitterで僕をフォローしている人のブログを読んだりすると、すごい人が一杯いるなー、と感じます。 



2009年11月19日

今更ながらGoのinterfaceとかstructとか・・・

Emacsのバッファにinterfaceとかstructとかをいろいろ試した時のコードがありました。ついでなので、載せておきます。

まずは、interface。interfaceって何かというとPython3のabcみたいなものです。えっ、わかんない?C++の純粋仮想クラスみたいなものです。えっ、だめ?Javaのinterfaceみたいなものです。
こんな感じで書きます
type MyInterface interface {
    Say() string;
}
Javaと同じで、interfaceに直接実装することができません。メソッドを定義できるかです。では、Javaのclass相当のことをするには、structを使います。基本的には、javaのfield値を指定します。
type MyStructBase struct {
    mesg string;
}
structに対してメソッドはfunc (self *MyStructBase) Say() string { return self.mesg; }のように書けば、このSayはMyStructBaseのメソッドになります。じゃあ、interfaceはどこよ?と言うことで、次のような関数を定義します。
func SaySomething(obj MyInterface) {
    mesg = obj.Say();
    fmt.Print(mesg + "¥n");
}
これは、引数にMyInerfaceという型のinterfaceを受け取ります。これを利用する側は、
obj := new(MyStructBase);
obj.mesg = "my struct base";
SaySomething(obj);
という感じです。SaySomethingの引数のMyInterface型のobjは、単にそのinterfaceが定義している関数をobjが持っているかどうかだけをチェックしています。だからduck typingなんですね。と言うか、いい加減なんですね。ちなみに、実行結果は"my struct base"と出力されるはずです。

次にMyStructBaseを継承したようなMyStructExtendを作ってみましょう。
type MyStructExtend struct {
    MyStructBase;
}
structのメンバーを書くところに直接基底クラスみたいなものを書きます。使うときは
obj := new(MyStructExtend);
obj.mesg = "my struct base";
SaySomething(obj);
です。実行結果も"my struct base"となります。MyStructBaseの実装がそのまま使えました
では、MyStructExtendに同じメソッドを追加します。func (self *MyStructExtend) Say() string { return self.mesg + "from MyStructExtend"; }
これを実行すると、"my struct base from MyStructExtend" となります。Javaのsuperみたいなことをするには、
func (self *MyStructExtend) Say() string {
    return self.MyStructBase.Say();
}
とします。これで、継承元のSay関数が呼び出されます。言語オタクはいろいろ言うかもしれませんが、僕は嫌いじゃないです。PythonなどのLLも外界との境界線上にはtype check(もしくは型宣言)があった方がいいと思っているので、このぐらいのいい加減さがいいです。

もっと、テスト用のコードを書いたんだけど、めんどいので、このぐらいで。

2009年11月18日

GoでHTTPサーバ その3 Cometもどき

GoでHTTPサーバの続きです。とって言っても、チャットサーバをHTTPっぽくしただけです。URLで/listenにアクセスすると、ずっと待ち続けます。URLが/say?message=なんかのメッセージにアクセスすると、「なんかのメッセージ」がlistenで待っているクライアントに配信されるだけです。


package main

import (
"http";
"log";
"io";
)

func startServer() {
// initialize
queue := make(chan string);
listen_chan := make(map [*http.Conn] chan string);

go func() {
for {
mesg := <- queue;
for _, c := range listen_chan {
c <- mesg;
}
}
}();

// http handlers
http.Handle("/", http.HandlerFunc(func(c *http.Conn, req *http.Request) {
path := req.URL.Path;
log.Stdout("Request URL: " + path);
http.ServeFile(c, req, "." + path);
}));
http.Handle("/listen", http.HandlerFunc(func(c *http.Conn, req *http.Request) {
reciever := make(chan string);
listen_chan[c] = reciever;
mesg := <- reciever;
io.WriteString(c, mesg);
listen_chan[c] = nil, false;
}));
http.Handle("/say", http.HandlerFunc(func(c *http.Conn, req *http.Request) {
mesg := req.FormValue("message");
queue <- mesg;
body := "Message \"" + mesg + "\" was sent";
io.WriteString(c, body);
}));

err := http.ListenAndServe(":1972", nil);
if err != nil {
log.Stderr(err.String());
return;
}
}

func main() {
log.Stdout("starting server...");
startServer()
}

やってはいけないこともやってしまう

スタートアップがやってはいけないこと10+1がなかなかおもしろいです。

アリエルができた時を振り返りながら見てみると、


1.  街のいい場所に立派なオフィスを借りてしまう

他人の金を自分の金のように使うな

アリエルができた当時はオフィスがなかったし、どちらかと言えば、このままオフィスなくてもいいじゃね?と思っていました。でも、なぜかオフィスができてしまいました。いい場所かどうかはわかりません。当時は割と安い方でした。ちなみに、一番最初の渋谷のオフィス(どこかの会社のを曲がり)はなぜか無料でした。 


2. 1回のツイートで何をしているか説明できない 

なぜあなたのプロダクトが優れているのか、短時間で説明できるようになれ 

  これは、そうだったかもしれません。


3. ざっと見回してもプログラマーがいない 

よい企業は彼らであふれている

残念ながらプログラマばかりでした。それはそれでどうかな?と思います。


4. PR会社と契約する(あるいはブログもツイッターも使ってない) 

素晴らしい企業は顧客がその企業のことをすすんで語るものだ

 途中から何かをやろうとしていたかもしれませんが、よく分かりません。


5. 間違ったことにお金を使っている 

コーヒーマシンではなく、プログラマによいイスとモニタと速いマシンを買ってやれ

 たぶん、日本の他の会社よりはいいですが、僕は全員に個室が欲しいです。


6. 解雇を躊躇する 

社内で方向性が異なるスタッフがいたら素早く対応すべきだ

 これって、アメリカと違って日本じゃ難しいんじゃないかな。変にやると訴訟になるし。ただ、アリエルができた時はみんな若かったので、その環境に慣れなくていなくなる人はいたけど。


7. インフラの選択を誤る 

私(スコーブル氏)はRackspaceの社員でありバイアスがかかっていると思うので、この件については誰かよいスタートアップに聞いてみるのがよい。

  ・・・


8. 早すぎる時期からベンチャーキャピタルにマネジメントと戦略をコントロールされてしまう
うーん、どうなんでしょう?ベンチャーキャピタルにもよるんじゃないかな?もしくは人によるのかもしれません。ただ、エンジニアはおとなしいので、対等に渡りあえるスーツが必要かもしれません。


9. クールすぎる社名やロゴ
 なんか、最初はすごい適当だったような・・・。


10. Yesといいすぎる。とりわけ技術的な決断に対して
うーん、これはどうとらえていいか分かりません。とりあえず、技術的な決断は結構やりとりがあったような気がします。


11. 詳しいからと古い技術を選んでしまう

これも微妙です。エンジニアは新しいから、おもしろそうだからと言う理由で技術を選んでしまうこともあります。やろうとしていることに対して、何が適切かじゃないかな?

まあ、最初はいろいろありましたが、なんでもいいから続けることが大事かもしれません。 



2009年11月17日

今日のgolang

Goの中からCのライブラリが呼べるのか・・・。でも、C++はどうなんだろう?

Stackless Pythonもすごそう。tokuhiromさんによると最近の「async/concurrencyブームにのっかって息をふきかえしてる」らしい。Twistedあやうし。っていうか、パフォーマンスはともかく、TwistedのDeferredGeneratorもおもしろいんだけどな。

それから、Goのevalは何者?ざっとコードを眺めると、evalの値をコンパイルしてネイティブコードにして実行しているみたいなんだけど・・・。これ使えば、LLのevalみたいな感じで使えるの?すげー。

GoでHTTPサーバ その2

rpcのパッケージもあるし、httpdのパッケージがあっても不思議ではなかった。もとは、これ。次はchannelまわりか。

package main

import (
"http";
"log";
)

func startServer() {
http.Handle("/", http.HandlerFunc(func(c *http.Conn, req *http.Request) {
path := req.URL.Path;
log.Stdout("Request URL: " + path);
http.ServeFile(c, req, "." + path);
}));
err := http.ListenAndServe(":1972", nil);
if err != nil {
log.Stderr(err.String());
return;
}
}

func main() {
log.Stdout("starting server...");
startServer()
}


GoのConcurrency

Goが広まるかどうかはよくわかりません。Chromeと融合するというお話もあるので、少なくともGoogleは使いそうです。スレッドをばんばん作るようなサーバを作るための言語かな?と思っていましたが、Chromeに絡めてくるとはちょっと意外でした。そんなGoですが、トップページにConcurrencyが特徴の一つとしてあげられています。Language Design FAQを読むとすごいです。
multiplex independently executing functions—coroutines, really—onto a set of threads
とあって、複数のスレッドでコルーチンが動いているような感じです。
When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked.
とあり、スレッド(コルーチン)内で何かがブロッキングIOをコールすると、ランタイムが勝手にそれを見つけてきてくれて、他のスレッドに切り替えてくれます。
他にも、コルーチンなので、計量スレッドになるとか書かれていますが、そのへんは大しておもしろくもありません。

さて、で、上のような仕組みって、結局Pythonとかでもできなくはないし、ありきたりと言えばありきたりです。でも、これがネイティブコードになると、どうやっているのか不思議です。Goのコードを書いていると、なんとなくスクリプトっぽさを感じます。duck typingのあたりやシンタックスもそうなんですが、コンパイルして実行するのが一瞬で、適当なシェルスクリプトなり、make && ./myappみたいに書いておけば、一瞬でコンパイル、実行できます。その辺もネイティブにコンパイルして実行していると言うことを忘れさせます。

で、goroutineがどんなネイティブコードをはくかはアリエルの井上さんがレポートしてくれるでしょう。

UNIXは体にいい

Goが公開され、オーサーの名前にKen ThompsonのようにUNIXの伝説の人が登場しています。基本的な設計だけをしたのかと思っていましたが、GoのコミットログをみるとKen Thompsonの名前で沢山のコミットがあります。中には「spell it with an "e"」のようなコミットログまであります。UNIXの年齢はちゃんとは覚えていませんが、UNIXが40年ぐらいだとすると、Ken Thompsonは60を超えているおじいちゃんのはずです。それでも現役で作業できるって素敵です。日本ではプログラマ35(40?)才定年説みたいなものがあったりしますが、多分、好奇心を持って楽しめれば何歳まででも現役のプログラマでいられるような気がします。そして、そうありたいです。

それから、先月号ぐらいのSoftware Designにカーニハン先生がのっていました。伝説の人たちは意外に長生きです。教育の方にシフトしたみたいですが、それでも現役で働いています。

UNIXは健康にいいのかもしれません。 



2009年11月14日

Goで超いい加減HTTPサーバを書いてみた感想

Goが公開されて、おもしろそうらしいので、GoでかなりはしょったHTTPサーバを書いてみました。その感想です。

まず、Goは名前がよくないです。ここでは、Goと言う言語がすでにあるから名前を変えてくれと言われているらしいですが 、変えて欲しいです。Issue9とか言う候補もあるらしいですが、まあ、僕はerlangのようにgolangでいいような気もします。ドメイン名もちょうどいいし。で、僕が名前を変えて欲しい理由は、グーグルさんで検索してもろくな検索結果が帰ってこないからです。これは悲しすぎます。

それでは、コードを書いた感想です。関数を実行して値を複数返せるのはすばらしいです。Pythonでコードを書くと当たり前のことが、CとかJavaとかだとできなくてフラストレーションの元でした。

それから、関数を抜けるときに実行する処理を書けるのもいいです。Javaだとtry〜finallyでやっていたことが気軽にできます。それから、returnするときに、そこに書かなくても途中で代入した結果を返してくれる機能とかもいいです。このあたりは小さなフラストレーションの固まりを解決してくれるのでいいところです。

でも、全体的にGoのシンタックスは好きではありません。99%ぐらいが慣れの問題だとおもいますが・・・。なんとなく、なじめません。

それから、goroutineはいいです。簡単に並列実行できます。本質的に難しいところは難しいのかもしれませんが、とってもいいところです。

インターフェースは、賛否両論あるところでしょうが、僕は好きです。実装が継承できないのは、うーんな気もしますが。それから例外がないのもちょっとなー。Javaのように例外でやり過ぎるのもどうかとは思いますが、例外のようなjumpが欲しいです。

ライブラリは、それほど使い込んでいないのでよく分かりません。まあ、最低限のことはできるぐらいはそろっています。最低限をどう定義するかは人によってまちまちでしょう。

ドキュメントがいまいち。まあ、僕はドキュメントはどうでもいいので、サンプルコードがかいてあればいいと思っているのですが、もうちょっと両方とも何とかならないかなー。

それから、まだ、チュートリアルちゃんと読んでません。長いです。英語です。会社のうさみみが、メーリスをつくったり、翻訳すると息巻いたりしています。翻訳してくれればちゃんと読むかもしれません。

 と言うことで、嫌いじゃないですが好きにもなれそうにありません。Pythonのようにインターラクティブモードがあれば好きになれるかもしれませんが。 



2009年11月13日

Goで超いい加減HTTPサーバ

超いい加減HTTPサーバを今はやりのGoで書いてみました。とってもいい加減です。カレントディレクトリのファイルをフィードしてくれます。ヘッダーのパースは、最低限のことしかしていません。レスポンスヘッダーもHTTP/1.0 200 OKしかかえしません。エラーがでたら無条件でブチッとコネクションを切ります。
goroutine楽です。connを閉じる場所が美しくないので、変えたい。


感想はこっち

package main

import (
"os";
"net";
"syscall";
"strings";
"fmt";
)

func Err(format string, v ...) {
fmt.Fprintf(os.Stderr, format + "\n", v)
}

func Msg(format string, v ...) {
fmt.Fprintf(os.Stdout, format + "\n", v)
}

func main() {
runServer()
}

func runServer() {
l, err := net.Listen("tcp", "127.0.0.1:1972");
if err != nil {
Err("Failed to Listen to 1972");
}
for {
conn, err := l.Accept();
if err != nil {
Err("Accept %s", err);
break
}
Msg("Request came");
go processRequest(conn);
}
}

func processRequest(conn net.Conn) {
defer conn.Close();

buffer := make([]byte, 1024);
headers := "";
for {
l, err := conn.Read(buffer);
if err == nil {
b := buffer[0:l];
headers += string(b);
count := len(headers);
if headers[count-4:count] == "\r\n\r\n" {
break;
}
} else if err == os.EOF {
Msg("EOF");
return;
} else {
Err("Err%s", err);
return;
}
}
url := strings.Split(headers, " ", 3)[1];
url = url[1:len(url)];
if len(url) == 0 || url[len(url)-1] == '/' {
url += "index.html";
}
fd, err1 := syscall.Open(url, syscall.O_RDONLY, 0);
if err1 == 0 {
conn.Write(strings.Bytes("HTTP/1.0 200 OK\r\n\r\n"));
fb := make([]byte, 1024);
for {
l, e := syscall.Read(fd, fb);
if e == 0 {
conn.Write(fb[0:l]);
}
if l == 0 {
break;
}
}
syscall.Close(fd);
}
Msg("done");
}

2009年11月12日

最近の気になる5つのこと

1. 野党のような与党と、与党の余韻に浸る野党がおもしろいなー。それから、「政治家としての責任」って、自分が言ったことを忘れること。
2. 池田先生と勝間氏との戦いが楽しかった。やっぱり戦いを野次馬としてみるのは楽しい。池田先生と勝間氏でトークライブやって欲しい。切込隊長さんが生暖かい司会をしてくれて、池尾先生が傍聴していて、ホリエモンが「そんなのどうでもいいから、起業しろ」みたいな感じで割って入って、金融日記を書いている人がそれらをなぜかまとめてくれる、と言うのを期待。
3. ちょっと前にクロージャ(Googleさんじゃないほう)が盛り上がっていたけど、Python始めた人にみんな言い過ぎ。で、Javaしか知らない人にクロージャを説明しようとして例がめちゃくちゃ悪かっただけのような気がする。大体、ファイルから読み出すのに"config.yaml"とかファイル名を直接指定なんてほとんど実際のコードではないでしょ。
4. Goとかクロージャ(Googleさんのほう)とか。まあ、クロージャの方はそれなりなんですが、Goはよく分からないです。まあ、ケン・トンプソンなのでいいものに違いない。

とりあえず、MacでGoを動かす

エンジニアならMacにXCodeやmercurialなどの開発環境が入っているのは当たり前だよね。ということで、
export GOROOT=~/myproj/gosrc
hg clone -r release https://go.googlecode.com/hg/ $GOROOT

でソースをとってきます。そして、環境変数をセットしてからビルドします。GOARCHの説明を読むと、intelのプロセッサしかだめなのかもしれません。Core2じゃないMacのひとは、そういう人はx86だけど買い換え時かもしれません。
export GOOS=darwin
export GOARCH=amd64
cd $GOROOT/src
./all.bash

でビルドします。プロキシの配下にいると、HTTP関係のテストで失敗してインストールできません。悲しいです。http_proxyなどの環境変数をセットすれば大丈夫なのかもしれませんが、run.bashのmake testをコメントアウトしてインストールします。~/binの下にインストールされます。僕は~/binにPATHが通っているのでその後は何もしなくても大丈夫。

で、インストールの説明ページにあるサンプルを動かします。6gとか6lとかうーむ。6gがコンパイラで6lがリンカーなのですね。うまくいけば6.outができていてちゃんと動きます。

Pascalのような、Pythonのような変な気分です。会社のうさみみがメーリスを始めたので、興味ある人はどうぞ。ちなみに、プロジェクトページのドキュメントは全部訳すと息巻いているようです。

2009年11月11日

jQuery派とクロージャ派

クロージャは、最近一部で盛り上がっている言語のお話じゃなくって、Googleが先日公開したクロージャライブラリの方です。

社内ではjQuery派とクロージャ派、およびどちらの勢力にも属さない3つの勢力に分かれています。どちらにも属さない日和見主義な人たちは無視しましょう。クロージャ派の言い分は、jQueryのコアライブラリは独特すぎてついていけないというものです。foreachとかの使い方をみても、独特です。さらに、uiライブラリが貧弱というものです。現在提供されているものは両手で数えられるぐらいしかないので、他のライブラリを見れば見劣りします。

jQuery派は、まあ、いろいろ考えてはいるようですが、純粋に技術的なことに関して言えば、GoogleのUIはシンプルすぎるとか、たくさん機能があるけど、今すぐ必要なものがないだとか、あげくに、IEじゃ動かないでしょ!とかいいだします。大体が言いがかりです。そして、技術的な議論をしたいのに「だって、Google嫌いだもん。結局Microsoftみたいなもんでしょ」と。

今会社で一番必要としていたのはUIライブラリなので、どうがんばってみたところでjQueryは不利です。 でも、jQuery派の人はクロージャに宗旨替えをしようとしていたのですが、話の成り行きからそれができなくなって頑なになっています。さて、どうなるでしょう?



2009年11月10日

アリエルにはボーナスがないという噂

来月はボーナス月です。アリエルには伝統的にボーナスがないです。業績分はともかく、基本的にボーナスって言うのは年俸を18でわって3を掛けたものを6月と12月にまとめて払う仕組みです。3じゃなくって、もう少し少なかったり多かったりする会社もありますが、そこは誤差です。会社がよほど業績が悪くない限り、ボーナスはもらえるはずです。

アリエルができた時から給料は年俸制でした。 年俸を12でわったものを毎月もらうか、18で割ってボーナス月に多くもらうか、自分で決めろと言われました。これは、人によって選択できるようにしようと、当時の社長は考えていたらしいですが、すぐにめんどくさくなって12で割ったものになりました。計算がしやすいように年俸も12できれいに割り切れる値になっていました。

さてさて、僕は選択を迫られた一人ですが、ひょっとしたら僕しか選択を迫られなかったかもしれません。結局、僕のせいで12でわるというのが残ったのかもしれません。で、12でわった方がいいというのは、できて間もない会社だったので、いつつぶれるかわかりません。ボーナスは前払いではなく、後払いです。先延ばしにして、もらえるはずの時に資金がショートしてもらえないと悲しいです。もらえるときにもらっておくのが吉です。という打算的な理由がありました。

なので、同じ年俸でもボーナスがある会社よりも一月の給料は多いです。

で、ボーナスがないと書きましたが、業績がよければ期末にボーナス(と言うかよく分かりませんが・・・)があります。これは業績と評価によって決まりますが、このおかげで、実際の年収は多分、他の会社よりは高いかもしれません。 業績分を社員に還元しているいい会社なのですが、他の人がボーナス月で浮かれているときには何もないので、寂しいと言えば寂しいのかもしれません。僕はなれてしまっているのであまり感じませんが、先日社員の人にちらっと言われました。でも、この仕組みをちゃんと理解していなかったようですが・・・。

さて、今は当時と違って会社がなくなるかもしれないという危機感は必要なくなりましたが、 会社ができた時はそんな感じだったというお話でした。



2009年11月9日

VirtualBoxにUbuntu 9.10を入れてMacっぽくした結果



Macっぽくした時の証拠画像。左上のGNOMEのアイコンはUbuntu Tweakだと変えられるみたいなことが書いてあるけど、変えられないです。オリジナルの画像をりんごに差し替えればいけますが、そこまでは僕はしません。

globalmenuは最新版じゃないとEclipseとかFirefoxが起動時に落っこちちゃうことがあるので注意が必要です。

それから、Ubuntu 9.04だと起動の画面やログイン画面などもMacっぽくなっていましたが、9.10だとそうなってくれません。滅多にログインするものでもないので、頑張りません。

2009年11月6日

VirtualBoxにUbuntu 9.10を入れてMacっぽくする

会社ではQuad CoreのマシンでVirtualBoxが動いています。そこにUbuntu 9.10をインストールしました。インストール直後にログインすると3Dのエフェクトが少しだけかかっています。ただ、エフェクトがかかるととても遅くなるので、3Dエフェクトは諦めます。VM上のことだから仕方ないのかもしれません。

さて、会社ではDual Monitorで使っていて、片方の画面はVirtualBoxをフルスクリーンで使っています。フルスクリーンだとVMで動いている感じがしなくていいです。さらにUbuntuの見た目をMacっぽくすると、一部の人は騙されおもしろいです。なので、カルマなコアラの9.10をMacっぽくします。昔と違って、かなり手順が簡略化されています。
まず、Mac4Linのサイトから最新版のMac4Linをダウンロードします。現在は、Mac4Lin_v1.0.tar.gzです。ついでにpdfがあって、そこにちゃんとした英語のドキュメントがあります。

ダウンロード後、解凍して
cd Mac4Lin_Install_v1.0/
./Mac4Lin_Install_v1.0.sh
と実行します。何か聞いてきたら「y」を入力して、パスワードを聞かれたらパスワードを入力します。次に、awn関係のパッケージをインストールします。とりあえず、こんな感じ
sudo apt-get install awn-applets-c-core awn-applets-c-extras awn-applets-python-core awn-applets-python-extras awn-manager
これで、下のパネル入らなくなったので、思いきって削除します。そして、アプリケーションのアクセサリのAvant Window Navigatorを機動します。下の方にドックが出現するので、右クリックして設定を開きます。ログイン時にAwnを自動起動するにチェックを入れて、あとは、お好きなように。
次に、壁紙をMacっぽいものに変えます。ホームディレクトリにMac4Lin_v1.0と言うフォルダがあるので、その中のWallpapersの中にわりとそれっぽい壁紙があります。また、別のところから落としてくるのもありかな。

Macと言えば、メニューはウィンドウの中ではなく、上のパネルの中です。これをやらないと意味がないです。まずは、ここにあるように最新版のglobalmenuをインストールします。Synapticマネージャを開いて設定のリポジトリを選択します。他のソフトウェアのタブに移動して追加で次の行を追加します。
deb http://ppa.launchpad.net/towolf/ppa/ubuntu karmic main
再読み込みしてからgnome-globalmenuをインストールします。まずは、上のパネルの左の方にあるメニューとかFirefoxのアイコンとかをことごとく消しちゃいます。そして、メイン・メニューのアイコンを追加。それから、Global Menu Panel Appletを追加します。それからPreferenceからGeneral Settingのタブにあるチェックをすべてつけて閉じます。Gnomeのアプリケーションのメニューはパネルの中に表示されます。これで、人を騙せます。

それからGnomeのアイコンは変えられるはずなんですが、変わってくれません。それはまた。