プログラミングの話
楽しいよね。
塩ビ板にマザーボードなどをマウントした
今日は以前買っておいて放置していた透明な塩ビ板(5mm厚)を使ってPCケース(というか板)を作ってみました。
塩ビ板に適当に穴を開けてそこにネジを通しただけです。
拡張ボード用の穴を全部開ける前がこんな感じ。
そして完成したのがこんな感じ。ちゃんと見るとわかりますが、拡張ボードの突起が挿さるための穴が開いています。
机の横に置いて Windows8 のインストーラを起動している風景です。
ちなみに塩ビ板は10mmのジュラコンスペーサを使って挟まれており、下はネジ頭の2mm+10mm、マザーボードとの間は10mmのスペースが開いています。
また、HDDはインチネジ(自分は国内標準のミリネジに対してインチキネジと呼んでいる)で固定すべきなのですが、なにぶんインチキなのでそんなものはストックになく、無理やりM3のネジで固定しました。そのうちなんとかします。
このマシンはサーバーとしてではなく、開発用として使う予定です。そのためのグラボや電源なども今日 Amazon でポチッってしまいました。ああ、散財が激しい……。
Stream#pipeの破棄イベントの伝播
あっさりハマってメモリリークさせまくったので報告。
さっそく本題。まず図を用意。
Readable Stream -(pipe)-> Transform Stream -(pipe)-> Writable Stream
みなさんご存知のデータの流れ。しかし、問題は破棄イベントの伝播方向。
Readable Stream が閉じた場合
- Readable Stream が閉じる
- Transform Stream が閉じる
- Writable Stream が閉じる
=> 全部閉じる
よいですね。
Writable Stream が閉じた場合
- Writable Stream が閉じる
- おしまい
_人人人人人人人人人人人人人人人人_ > 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() が返すデータのサイズについて
@KOBA789 ずっと気になってるのが、ブログにあった「引数なしの read() を一度呼べば全てのデータが吸い出せるという前提」なんだよね。これがなんか stream の考え方とずれている感じが引っかかってる。そこも言及されたブログだとより良いと思います。
2013-02-11 14:37:24 via Echofon to @KOBA789
とか言われたのでちょっと考えてみたけれど、適切なバッファサイズとか流量とか、まだよくわかってない……。なのでもう少し流量制限について調べて、触ってみて、なにかわかったらまた記事書こうと思う。