Write and Run

it's a simple way, but the only way.

**langのおべんきょしてます

勢いに任せて GolangErlang の本を買いました。前者は2冊、後者は1冊です。前者2冊はいずれも電車の中で、後者1冊は枕元に置いて寝る前に読んでます。おもしろいです。どっちかっていうと Elang の方がロマンがあっておもしろいです。でも Golang の方が低レイヤな感じがあってそれはそれで味があって楽しいです。

それだけです。おもしろいです。

塩ビ板にマザーボードなどをマウントした

今日は以前買っておいて放置していた透明な塩ビ板(5mm厚)を使ってPCケース(というか板)を作ってみました。

塩ビ板に適当に穴を開けてそこにネジを通しただけです。

拡張ボード用の穴を全部開ける前がこんな感じ。

f:id:koba789:20130325180436j:plain

そして完成したのがこんな感じ。ちゃんと見るとわかりますが、拡張ボードの突起が挿さるための穴が開いています。

f:id:koba789:20130325202512j:plain

机の横に置いて Windows8 のインストーラを起動している風景です。

f:id:koba789:20130325204344j:plain

ちなみに塩ビ板は10mmのジュラコンスペーサを使って挟まれており、下はネジ頭の2mm+10mm、マザーボードとの間は10mmのスペースが開いています。

また、HDDはインチネジ(自分は国内標準のミリネジに対してインチキネジと呼んでいる)で固定すべきなのですが、なにぶんインチキなのでそんなものはストックになく、無理やりM3のネジで固定しました。そのうちなんとかします。

このマシンはサーバーとしてではなく、開発用として使う予定です。そのためのグラボや電源なども今日 Amazon でポチッってしまいました。ああ、散財が激しい……。

Stream#pipeの破棄イベントの伝播

あっさりハマってメモリリークさせまくったので報告。

さっそく本題。まず図を用意。

Readable Stream -(pipe)-> Transform Stream -(pipe)-> Writable Stream

みなさんご存知のデータの流れ。しかし、問題は破棄イベントの伝播方向

Readable Stream が閉じた場合

  1. Readable Stream が閉じる
  2. Transform Stream が閉じる
  3. Writable Stream が閉じる

=> 全部閉じる

よいですね。

Writable Stream が閉じた場合

  1. Writable Stream が閉じる
  2. おしまい
_人人人人人人人人人人人人人人人人_
> Writable Stream しか閉じない <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

=> 源流側が破棄されない

まとめ

正直、知らんかった(バカ)。

"Stream"について考えていたらConduitを知った

Iteratee ってちょっと古かった感じですかそうですか。今更騒ぎ立ててごめんなさい。

Iteratee わけわかんねーな、run ってなんだよとか思っていたら、Conduit を見つけた。push 型から pull 型へ先祖返り、と。なんだか Stream(1) から Stream2 への移行みたいなことがこっちでも起きてるんだな。

さて、Iteratee について疑問だったことといえば、Enumeratee 同士の結合がなかったことだけど、Conduit では Conduit 同士を結合できるっぽい。ちなみに、流れ的にはこんな感じ。

Source -pull-> Conduit -push-> Sink

Conduit が左から引っ張りだして右に突っ込む感じのよう。まだよくわからん(コードも読んでないから)雰囲気だけど。

ちなみに結合則(っていうのかな?)をまとめるとこんな感じ。(相変わらずのオレオレ記法でごめんなさい)

 Source  $= Conduit := Source
Conduit =$  Sink    := Sink
Conduit =$= Conduit := Conduit

BNF を書いているみたいでとても素敵だ。Conduit を Source と結合しても Sink と結合してもいいあたり、とても美しい。やばい。

詳しくは とか Data.Conduit とか読んで俺も今から勉強します。

"Stream"について考えた(それとIteratee)

タイトルは釣り。どっちかというと Iteratee がメイン。(だってみんな Iteratee とか見ても記事開かないでしょ)

1週間くらい Stream について考え続けて、やっぱりわからなくて。でも、こんな基本的な概念、誰かが既に考えつくしてるに違いない、と思ってググってみたら、あった。そして、またお前か、Haskell

Iteratee

ほとんど Stream。モナドとかオートマトンとか言い始めるときりがないので演算子とその働きだけ大雑把に眺めてみた。

Gist: Iteratee とその演算子の働きとか。すっごく大雑把で、記号も適当ですが雰囲気だけ。

==================================================================
                Enumerator -> Enumeratee -> Iteratee
==================================================================
                                            Iteratee >>== Iteratee
                                         := Iteratee
------------------------------------------------------------------
                Enumerator $$               Iteratee
                                         := Iteratee
------------------------------------------------------------------
                              Enumeratee =$ Iteratee
                                         := Iteratee
------------------------------------------------------------------
                Enumerator $= Enumeratee
             := Enumerator
------------------------------------------------------------------
Enumerator >==> Enumerator
             := Enumerator
------------------------------------------------------------------

Stream に置き換えると、Enumerator が Readable、Enumeratee が Transform、Iteratee が Writable、という感じ。ちょっと違うけど、そんな感じ。

Stream と違うのは、Enumerator 同士の結合と、Iteratee 同士の結合。これが型と相まって地味に便利っぽい。

ということで JavaScript で Iteratee を実装してみてます。どうなることやら。

続: Stream2のモヤモヤ

追記で書くほどの分量でもなくなってきたので別にしました。

まず結論からいうと、

ドキュメントが追いついてない

だけだったようです。このコミット streams: Support objects other than Buffers · 444bbd4 · joyent/node · GitHub での変更が、ドキュメントに反映されてないようです。ドキュメントは the entire buffer とか言ってるけど、ソースコード的には objectMode のときには size 1 なのね……

If we are in "objectMode" mode then howMuchToRead will
always return 1, state.length will always have 1 appended
to it when there is a new item and fromList always takes
the first value from the list.

俺の半日を返せと。

本題

さて、謎の原因がわかったところで本題。

現状の stream2 は buffer, string, object を chunk としてサポートしている。しかし、他の2つとくらべて object は特殊。どれくらい特殊か、下の表にまとめてみた。

length プロパティ 連結の可否 任意の型のデータの格納の可否
string ある concat メソッドで可能 不可
buffer ある concat メソッドで可能 不可
object 意味ない object の連結? なにそれ 可能

圧倒的に浮いてる。同列に並べちゃいけない。それに対して array はどうか。

length プロパティ 連結の可否 任意の型のデータの格納の可否
string ある concat メソッドで可能 不可
buffer ある concat メソッドで可能 不可
array ある concat メソッドで可能 可能

これでしょ。サポートするなら。

ストリームの chunk は joinable で size(length) を持つべきだと思うんです。どこで切ってもよく、どこでつなげてもいい、そういうデータが chunk であるべきだと思うんですよ。

結論

object のサポートなんてやめて、array をサポートすべき。

とはいえ

「過去のモジュールでは object を chunk として流すものも多い。互換性はどうするんだ」とかいう反論があるかもしれない。でも個人的には stream2 は stream と決別して進化して欲しいし「歴史的経緯」なんてもので汚れてほしくない。stream1 は生かしつつ、stream2 が別に生まれるくらいでいいんじゃないかとも思う。

引数なし read() が返すデータのサイズについて

とか言われたのでちょっと考えてみたけれど、適切なバッファサイズとか流量とか、まだよくわかってない……。なのでもう少し流量制限について調べて、触ってみて、なにかわかったらまた記事書こうと思う。