Smalltalkのtは小文字です

id:sumim:about

オブジェクト指向の“モヤッと”の正体を知りたくなったら、id:sumim:20080415:p1id:sumim:20040525:p1 がお役に立つかも…。


 

2014-08-26

[] ひさしぶりに AO bench を試したら Squeak/Pharo が(少しだけど 圧倒的に)VisualWorks より速くなっていたでござるの巻



Island Life - Gaucheでaobench再び に触発されて、マシンも処理系も前回から刷新されたことだしと試してみました。コードはいろいろとひどいのであらためて書き下ろしたい気持ちもありましたが、へんに Smalltalk っぽく書き換えたところで遅くなるだけなので、前回のまま使いました。使用したマシンのスペックは Intel Core i7-4650U @ 1.7GHz/2.30GHz、Win 8.1 (64 bit)です。


 処理系   時間 
 VisualWorks 7.10.1 (64 bit)  34 sec 
 Pharo 3.0 / Cog JIT VM  27 sec 
 Squeak 4.5 / Cog JIT VM  26 sec 
 Squeak 4.5 (trunk46-spur.image) / Cog Spur JIT VM  13.5 sec 
 Squeak 4.3 / Cog JIT VM  37 sec 
 Squeak 4.3 / 旧 非JIT VM  114 sec 
 Ruby 2.1.2  64 sec
 C  1.7 sec 

ざっと C の 15倍遅いくらいでしょうか。Cog VM おそるべし。


[追記] …と思ったら、id:squeaker さん情報によれば Cog VM はさらに進化しているらしく、最新の Spur というバージョンを使うと C の 8倍程度の遅さをたたき出したのでありました。すばらしい。


Cog Spur VM とそれに対応した仮想イメージは、こちらから入手可能です。

[追記ここまで]


参考まで Gauche-0.9.5_pre1 は GAUCHE_AVAILABLE_PROCESSORS = 1 で 54s 、この制約をつけないでコア全部使うと 29s でした(cygwin64 環境。前後しますが Ruby、C も同じ)。


あと、Gauche は 0.9.4 も 0.9.5_pre1 も cygwin64 では現状なぜか gc のあたりでビルドに失敗するので(trunk にはパッチが当たっているはずなのですが…)、C はよくわからないながらもエラーから判断して ./gc/include/gc.h の _data_start__ をのたぐいを __data_start__ に書き換えて無理矢理とおしたのを使っています(下はそのときのエラー)。

main.o:main.c:(.rdata$.refptr._bss_start__[.refptr._bss_start__]+0x0): `_bss_start__' に対する定義されていない参照です
main.o:main.c:(.rdata$.refptr._data_start__[.refptr._data_start__]+0x0): `_data_start__' に対する定義されていない参照です
main.o:main.c:(.rdata$.refptr._bss_end__[.refptr._bss_end__]+0x0): `_bss_end__' に対する定義されていない参照です
main.o:main.c:(.rdata$.refptr._data_end__[.refptr._data_end__]+0x0): `_data_end__' に対する定義されていない参照です
collect2: エラー: ld はステータス 1 で終了しました

2014-08-06

[] 九州の七つの県を三色で塗り分ける問題を Squeak Smalltalk



688 :デフォルトの名無しさん:2014/08/03(日) 16:21:36.50 ID:vVRF2pWw
お題:九州の七つの県を三色で塗り分ける。

プログラミングのお題スレ Part4

| 九州 配色 状態 待行列 |
九州 := {
   #福岡 -> #(佐賀 熊本 大分).
   #佐賀 -> #(福岡 長崎).
   #長崎 -> #(佐賀).
   #大分 -> #(福岡 熊本 宮崎).
   #熊本 -> #(福岡 大分 宮崎 鹿児島).
   #宮崎 -> #(大分 熊本 鹿児島).
   #鹿児島 -> #(熊本 宮崎)
}.

配色 := 九州 inject: Dictionary new into: [:辞書 :kv | 辞書 at: kv key put: #(赤 青 黄) asOrderedCollection; yourself].
配色 at: #福岡 put: #(赤) asOrderedCollection.
状態 := 九州 collect: [:kv | kv key -> (配色 at: kv key) -> (kv value collect: [:val | 配色 at: val])].
待行列 := OrderedCollection with: 状態.
[待行列 notEmpty] whileTrue: [
   | 県と候補色群 |
   状態 := 待行列 removeFirst.
   配色 := 状態 collect: #key.
   県と候補色群 := 配色 detect: [:kv | kv value size > 1] ifNone: [^配色 collect: [:kv | kv value: kv value first; yourself]].
   県と候補色群 value do: [:候補色 |
      | 次状態 |
      次状態 := 状態 veryDeepCopy.
      (次状態 detect: [:kv | kv key key == 県と候補色群 key]) key value removeAllSuchThat: [:val | val ~= 候補色].
      次状態 do: [:kv | kv key value size = 1 ifTrue: [kv value do: [:vals | vals removeAllFoundIn: kv key value]]].
      (次状態 noneSatisfy: [:kv | kv key value isEmpty]) ifTrue: [待行列 add: 次状態]]
]
=> {#'福岡'->#'赤' . #'佐賀'->#'青' . #'長崎'->#'赤' . #'大分'->#'青' . #'熊本'->#'黄' . #'宮崎'->#'赤' . #'鹿児島'->#'青'} 

読み下すとき、kv のキーが何で対応する値がなんなのかわからずピンとこないのでイマイチ。

2014-07-29

[] Coffee Time Challenges, Q13 How many を Squeak Smalltalk



ときどきの雑記帖″ 2014年7月(下旬) 経由で。(ネタバレ注意)


13) How many

Challenge: ABCDEFGHIJ is a ten-digit-number. All of the digits are distinct. If 11111 divides it evenly, how many possibilities are there for ABCDEFGHIJ?

Coffee Time Challenges

方針は合っているはずなので、あとはスタート値に注意ですね。

((1023456789 roundTo: 11111) to: 9876543210 by: 11111) count: [:each | each asString asSet size = 10]  "=> 3456 "

2014-05-27

[] Squeak Smalltalk で 配列を交互に分配




Squeak Smalltalk でならどう書くかなぁ…と、いろいろ考えてみたのですが、いまひとつしっくりくるものがないので、いくつか思いついた書き方をざっくばらんに晒しておきます。


お題は、#(x0 y0 x1 y1 x2 y2) を #( (x0 x1 x2) (y0 y1 y2) ) のように分配してまとめるというもの(元はリストなのですが Smalltalk なので配列に読み替えます)。


オーソドックスに #( (x0 y0) (x1 y1) (x2 y2) ) という中間生成物を介して作る方法だとこう書けます。

(#(x0 y0 x1 y1 x2 y2) groupsOf: 2 atATimeCollect: [:pair | pair])
   inject: #(() ()) into: [:sum :each |
      sum with: each collect: [:a :b | a, {b}]]  "=> #((x0 x1 x2) (y0 y1 y2)) "

こういうときは、入れ子の配列を二次元配列に見立てて、行と列を入れ替える #transpose とか #transposed みたいな節操のないメソッドが欲しくなります。

SequenceableCollection >> transposed
   | colns |
   colns := (self species new: self first size) collect: [:idx | self first species new].
   self do: [:each | colns := colns with: each collect: [:coln :elem | coln copyWith: elem]].
   ^colns
#('abc' 'def') transposed  "=> #('ad' 'be' 'cf') "
(#(x0 y0 x1 y1 x2 y2) groupsOf: 2 atATimeCollect: [:xs | xs]) transposed  "=> #((x0 x1 x2) (y0 y1 y2)) "

余談ですが、ここで引数を返すだけのブロック(無名関数)である [:xs | xs] をシンボル #yourself に置き換えられないのは、メソッド #groupsOf:atATimeCollect: が第二引数(通常はブロック)に対して numArgs をして 1 かそれ以外で条件分岐をしているというありがた迷惑な実装のためです。

SequenceableCollection  >> groupsOf: n atATimeCollect: aBlock 
   | passArray |
   passArray := aBlock numArgs = 1.
   ^(n to: self size by: n)
      collect: [:index | 
         | args |
         args := (self copyFrom: index - n + 1 to: index) asArray.
         passArray
            ifTrue: [aBlock value: args]
            ifFalse: [aBlock valueWithArguments: args]]

このため、ブロックはグループを配列としてまるごとを受け取る処理も、その要素を個別にブロック引数に受け取る処理としても書けるようになっていて便利ではあるのですが、あいにくブロックの代わりにシンボルを渡すと破綻します(なお、エラーにならないことからわかるようにシンボルも numArgs への応答はできているので、破綻しないように細工することは簡単です)。個人的にはこういう一見便利そうなカラクリにはなるほどっ!と思うよりはイラッ!とさせられることのほうが多いです。


ありがた迷惑といえば、最近の String>>#, の実装もそうで、引数を asString するようになってしまったため、文字列以外の物を文字列として結合するのには便利なのですが、

'abc', 123 "=> 'abc123' "

しかし、バイト列に見立てた配列を連結するとか以前の実装に依存したちょっと変態的なコードを書こうとしたときにそれが妨げられて脱力します。まあ難しいところです。

'abc', #(65 66 67)  "=> 'abc#(65 66 67)'。'abcABC' を期待 "

閑話休題。


Smalltalk の配列は要素の追加ができませんが、OrderedCollection や WriteStream のインスタンスを使えば破壊的に順次追加する処理を書け、さらに #atWrap: を使ってひとひねりできます。

| colns |
colns := #(() ()) collect: #asOrderedCollection.
#(x0 y0 x1 y1 x2 y2) doWithIndex: [:each :idx | (colns atWrap: idx) add: each].
^colns collect: #asArray  "=> #((x0 x1 x2) (y0 y1 y2)) "
| strms |
strms := #(() ()) collect: #writeStream.
#(x0 y0 x1 y1 x2 y2) doWithIndex: [:each :idx | (strms atWrap: idx) nextPut: each].
^strms collect: #contents  "=> #((x0 x1 x2) (y0 y1 y2)) "

もうひとひねりして、追加先のコレクションやストリームをローテートする書き方もできますが、これはちょっとやり過ぎでしょうね。^^;

| colns |
colns := #(() ()) asOrderedCollection collect: #asOrderedCollection.
#(x0 y0 x1 y1 x2 y2) do: [:each | (colns add: colns removeFirst) add: each].
^colns asArray collect: #asArray  "=> #((x0 x1 x2) (y0 y1 y2)) "

と、いいつつさらに悪のり。

| strm colns |
strm := #(x0 y0 x1 y1 x2 y2) readStream.
colns := #(() ()) asOrderedCollection collect: #asOrderedCollection.
[strm atEnd] whileFalse: [(colns add: colns removeFirst) add: strm next].
^colns asArray collect: #asArray  "=> #((x0 x1 x2) (y0 y1 y2)) "

目先を変えて Matrix のインスタンスを使う手もあります。が、Array2D の代替として導入されたわりに、いまいち頼りにならない Matrix のことなので、これを使って書ける処理もそれなりです。

| mat |
mat := Matrix rows: 3 columns: 2 contents: #(x0 y0 x1 y1 x2 y2).
^(1 to: mat columnCount) collect: [:idx | mat atColumn: idx]   "=> #((x0 x1 x2) (y0 y1 y2)) "

総じて、スマートに書くことができず残念な結果に終わりましたが、いろいろと考えたり考えさせられたりして楽しかったのでよしとしましょう。

2014-02-06

[] 誰得かわからないSqueak Smalltalkを使った関数型プログラミングっぽい話



当初、誰向けかわからないCommon Lispでの関数型プログラミング入門とその未来 - 八発白中 に例にあがっているコードを Squeak Smalltalk ならどう書けるかというような、少しは有益なことを書こうかと思っていたら、のっけからネタに走ってしまって失敗しました。ごめんなさい。



▼関数の定義とコール(ネタ)

Smalltalk ではまずクラスを作り(その際、インスタンス変数などを宣言し)メソッドを登録することで、そのクラスのインスタンスであるオブジェクトの振る舞いを決める、というやりかたをします。しかし「メソッド」などといったところで、クラスに属しているだけでただの関数です。

通常であればこの“関数”は、オブジェクトに「メッセージ」と称される「関数名(セレクターとも言う)と引数」を組にした情報*1を送ることで動的にコールされますが、もし静的コール*2もできればもっと普通に関数として運用可能なはずです。

処理系ごとに方法が異なりますが(可不可も含め)、実は Smalltalk でも関数の静的コールは可能だったりします。たとえば Squeak Smalltalk であれば、メソッドの定義(とクラスへの登録)とその実体の取得、静的コールはそれぞれ次のように書いて実行できます。

"関数の定義とクラスへの登録 = 関数を定義したいクラスにコード文字列をコンパイルさせる"
Number compile: 'foo ^self' "<= レシーバーを返す関数 #foo を定義し、仮に Number に登録 ".

"関数の取得"
(Number >> #foo) "=> コンパイルされた関数の実体の取得。なお #〜 はシンボルのリテラル式 ".

"関数の静的なコール"
(Number >> #foo) valueWithReceiver: 'string' arguments: #() "=> #foo を静的にコール ".

静的なコールなのでいわゆるオブジェクト指向プログラミングの文脈からは外れ、クラス(この場合Number クラス)は単なる関数の置き場所に過ぎません。実際、Number とは縁もゆかりもない文字列である 'string' をレシーバー(もちろんこの呼び名も今や意味をなしておらず、「第一引数に」と読み替えてよい)にして #foo メソッドをコールできている点に注目してください。お手元に処理系があれば、上の最初の式を評価する(alt/cmd + d か、右クリックメニューから do it )かクラスブラウザを使って Number>>#foo を定義後、最後の式を評価(alt/cmd + p か、右クリックメニューから print it )すると、レシーバーとして与えた 'string'(実行コンテキスト内では self )がちゃんと返ってきます。

もし 'string' に対して foo というメッセージを送って、#foo を通常通り動的にコールしようとしても、Smalltalk で唯一のエラーともいえる「そんなメッセージ投げられても、何すりゃいいのかわかんねーぞ!」エラーを吐きます。そもそも 'string' のクラスやそのスーパークラス群は Number にある関数 #foo のことなど何一つ知るはずもないので、当たり前といえば当たり前ですね。

'string' foo  "=> MessageNotUnderstood: ByteString>>foo "

試しに階乗を求める #fact も定義してみましょう。どうせ静的にコールするため、関数の置き場所はどこでもよいので、今度は String に登録してみます。

String compile: 'fact
   self < 2 ifTrue: [^self].
   ^self * (String >> #fact valueWithReceiver: self-1 arguments: #())'.
(String >> #fact) valueWithReceiver: 10 arguments: #().  "=> 3628800 "

ちゃんと答えが返ってきますね。ただ、ここまで書いていまさらですが、関数のコールに valueWithReceiver: 10 arguments: #(). とかいちいち長たらしくていけません。



▼関数の定義とコール(仕切りなおし)

そんなわけもあってかなくてか(←ないです)、Smalltalk では通常、関数を単体で定義するにはブロックという無名関数オブジェクトを用います。定義はゼロ個以上の式を [ ] で括るだけです。名前を付けたいときは、別途、変数を宣言してそれを束縛してください。

| func |
func := [:a :b | a + b].
func value: 3 value: 4  "=> 7 "

引数がなければそのまま関数本体を記述し、引数があるときは「:引数名」を列挙して最後に | で区切って関数本体の記述を続けます。

引数のない関数では「value」を、引数がある関数では「value: 引数 」を引数の数だけ繰り返して構成したメッセージを関数に送ることでコールできます*3。value とか value: 3 value: 4 とか通常の言語の関数コールの記述より長たらしくていけませんが、(Integer >> #+) valueWithReceiver: 3 arguments: #(4) とかいちいち書くよりは少しはマシなので我慢しましょう。


再帰も書けます。が、再帰的呼び出しのために変数名が未定義であると評価するたびにコンパイラに指摘されるのがウザイです。

| fact |
fact := [:n | n < 2 ifTrue: [n] ifFalse: [n * (fact value: n-1)]].
   "=> fact appears to be undefined at this point Proceed anyway? "
fact value: 10  "=> yes を選べば、普通に 3628800 を返してくる "

http://squab.no-ip.com/collab/uploads/undefined_var_alert.png


表示されたポップアップでメニューで yes を選べば、警告を無視して(他にエラーがなければ)コンパイルは完了し、普通に走らせることはできるのですが、毎回それをするのは面倒なので、再帰関数を定義したいときは、いったん関数名にしたい変数を nil などに明示的に束縛しておき、直後に改めて関数本体を再代入するとよいようです。

| fact |
fact := nil.
fact := [:n | n < 2 ifTrue: [n] ifFalse: [n * (fact value: n-1)]].
fact value: 10  "=> 3628800 "

なお、末尾再帰最適化とかはないです。が、コールスタックはメモリの許す限り積めるので、メモリを食いつぶしたな…と気付く時点(メモリ不足のアラートが出るか、VM ごと落ちる)で、きっとそれはなにか意図しないことが起こっているか、意図したとおりに動いていたとしても現実的な時間では終わらないコードであることが多いです。


ブロックの返値としては最後の式の結果が使われます。メソッドと違い、ブロックでは ^ を用いて関数の途中で抜けることができません。オーソドックスには、この階乗の例のように条件分岐などをネストする必要があります。

Squeak Smalltalk や VisualWorks(Cincom Smalltalk)では BlockClosure>>#valueWithExit が使えるので、この手のカラクリを活用するのもよいでしょう。条件分岐だけでは対応しにくいネストしたループ内からの脱出とかも可能です。ただデフォルトの #valueWithExit の定義のままでは値を持って抜けることができないので、返値を持って回る変数を用意するなどの工夫が必要です。

| func |
func := [:stop |
   | result |
   [:exit |
      1 to: Float infinity do: [:m |
         m = stop ifTrue: [result := m. exit value]
      ]
   ] valueWithExit.
   result].
func value: 100 "=> 100 "


高階関数

よくある map の役割は Smalltalk では #collect: というメソッドが担当します。

#(1 2 3 4 5) collect: [:x | x + 1]  "=> #(2 3 4 5 6) "

[:x | x + 1] は無名関数でこれは第一級オブジェクトなので、変数に代入したり、あらためてそれを関数コール時に引数として渡すこともできます。*4

| plusOne |
plusOne := [:x | x + 1].
#(1 2 3 4 5) collect: plusOne  "=> #(2 3 4 5 6) "

さらに Squeak や Pharo では、単項メッセージのセレクター(シンボル)を渡すこともできます。

3 squared  "=> 9 "
#(1 2 3 4 5) collect: #squared  "=> #(1 4 9 16 25) "

内部的にはシンボルを同名の単項メッセージとして各要素に送ってその返値を得ているだけなので、Lisp などでシャープクオートマクロを使って関数を得ているのとは意味が違いますが、見た目はそれっぽくてかっこいいです。


あと、高階関数の話からは逸れてしまいますが、Squeak や Pharo の場合さらに、たとえば #squared のように Collection に定義されているメソッドならそのまま配列などのコレクションオブジェクトに対してメッセージとして送信、同名メソッドを動的にコールすることも可能です。

#(1 2 3 4 5) squared  "=> #(1 4 9 16 25) "

参考まで、同様のことができるメソッド名(セレクター)を列挙するコードとその結果を示します。

#('math functions' 'arithmetic')
   inject: #() into: [:acc :cat | acc, (Collection allMethodsInCategory: cat)]
#(abs arcCos arcSin arcTan average ceiling cos degreeCos degreeSin exp floor 
ln log max median min minMax negated range reciprocal roundTo: rounded sign 
sin sqrt squared sum tan truncated * + - / // \\ raisedTo:)

Smalltalk では reduce は #inject:into: を使います。

#(1 2 3) inject: 0 into: [:sum :x | sum + x]  "=> 6 "

もちろんこの場合は #+ でもOKです。

#(1 2 3) inject: 0 into: #+  "=> 6 "

最近のバージョンの Squeak や Pharo には、inject: キーワードの引数として初期値を与える代わりに、レシーバーの第一要素を用いるバリエーションとして #reduce: が用意されています。

#(1 2 3) reduce: #+  "=> 6 "

これまた余談ですが、Squeak や Pharo には Collection>>#sum があるので reduce: #+ に限っては無用です。

#(1 2 3) sum "=> 6 "
{Color red. Color green. Color blue} sum "=> Color white "


無名関数や #reduce: を(あえて)使って sum や factorial を定義すると例えばこんなふうに書けます。

| sum |
sum := [:xs | xs reduce: #+].
sum value: #(1 2 3 4). "=> 10 "
sum value: (1 to: 100). "=> 5050 "
sum value: {Color cyan. Color magenta. Color yellow}. "=> Color white "
| factorial |
factorial := [:x | (1 to: x) reduce: #*].
factorial value: 10. "=> 3628800 "

ところで Common Lisp の mapcar は複数のリストをとってこんなことができます。

(mapcar #'list '(1 2 3) '(a b c) '(松 竹 梅))  ;=> ((1 A 松) (2 B 竹) (3 C 梅))

が、Smalltalk の #collect: はこうした凝ったことはできません。そもそも、Smalltalk には文法の制約から可変長引数というしくみ自体がありません。

もはや関数型ぜんぜん関係なくなっちゃいますが、上の Common Lisp のコードの動きを想像して Squeak や Pharo で手続き的に書くとこうなります。

(#((1 2 3) (a b c) (松 竹 梅)) collect: #readStream) in: [:ss | ss collect: [:x | ss collect: #next]]
=> #(#(1 #a #'松') #(2 #b #'竹') #(3 #c #'梅')) 


▼関数合成

| compose plusOne |
compose :=[:fs | fs reduce: [:g :f | [:arg | f value: (g value: arg)]]].
plusOne := [:x | x + 1].
#(1 2 3 4 5) collect: (compose value: {plusOne. #sin})
=> #(0.909297426825682 0.1411200080598672 -0.756802495307928 -0.958924274663138 -0.279415498198926)



▼conjoin & disjoin

| cojoin |
cojoin := [:fs | fs reduce: [:g :f | [:arg | (f value: arg) and: [g value: arg]]]].
(cojoin value: #(isZero isInteger)) value: 0  "=> true ".
(cojoin value: #(isZero isInteger)) value: 0.0  "=> false ".
| disjoin positive |
disjoin := [:fs | fs reduce: [:g :f | [:arg | (f value: arg) or: [g value: arg]]]].
positive := [:x | x > 0].
(disjoin value: {positive. #negative}) value: 100  "=> true ".
(disjoin value: {positive. #negative}) value: 0  "=> false ".
| complement |
complement := [:f | [:x | (f value: x) not]].
(complement value: #isZero) value: 0  "=> false ".


▼まとめ

  • Smalltalk のメソッドは、通常は「メッセージ」を介して動的にコールされるが、静的にもコールできる
  • Smalltalk のメソッドの実体を手繰って静的にコールすれば普通に関数として使えなくはないが、いろいろめんどくさい
  • Smalltalk で関数を使いたければ、メソッド実体より普通にブロック(無名関数)を使うほうがいい つーか、使うべき
  • Smalltalk のブロックリテラル [〜] は Commpn Lisp の (lambda 〜) より lambda と書かなくていいぶん短くすっきり
  • でも呼び出しは value とか value: 3 value: 4 とかの長ったらしいメッセージの送信なのでプラマイゼロ、むしろマイ
  • 素の Smalltalk のやり方にも、関数型プログラミングっぽい側面はある
  • Squeak や Pharo にある、ブロックの代わりにシンボルを渡せる機能は、さらに関数型っぽさを醸し出す
  • かなり gdgd になったが気にしない

*1:たとえば 3 + 4 なら 3 へ + 4 というメッセージの送信を意味し、+ がセレクタ、4 が引数です。4 between: 3 and: 5 なら between: 3 and: 5 がメッセージ、between:and: がセレクタ、3 と 5 が引数になります。メソッド名はコロンも含まれ、そのコロンの直後で分断してそこに引数を挿入してメッセージを構成するところが、通常であれば 4.between:and:(3,5) のように記述するであろう他の言語と Smalltalk のメッセージ式とが違うところです。

*2:ここでは呼びたいメソッドを定め、ずばりそれをコールするという意味で使っています。

*3:内部的には、#value: #value:value: #value:value:value: はそれぞれ独立した別個のメソッドとして定義されています。#value:value:value:value: まで用意されていて、それ以上の引数が必要な場合は #valueWithArguments: を使い、引数は配列の要素として渡します。

*4:ただし条件分岐(たとえば #ifTrue:ifFalse:)など一部のメソッドはコンパイル時にインライン展開されるため、変数を介してブロックを間接的に渡すことができないこともあります。

 
2004 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 08 | 10 | 12 |
2013 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 11 | 12 |
2014 | 01 | 02 | 05 | 07 | 08 |

最近のコメント

1. 08/26 sumim
2. 08/26 squeaker
3. 08/07 sumim
4. 08/07 squeaker
5. 06/26 squeaker

最近のトラックバック

1. 01/30 no_orz_no_life - Erlangとジャンケン
2. 12/31 檜山正幸のキマイラ飼育記 - J言語、だってぇー?
3. 09/04 Twitter / @atsushifx
4. 07/06 みねこあ - オブジェクト指向 と FizzBuzz
5. 08/07 大島芳樹のカリフォルニア日記 - ランダムな文字列の中に隠された...

この日記のはてなブックマーク数
1307118