Write and Run

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

フレームワーク使うな的な話を見て

最初からフレームワークの使い方だけを勉強するようなことをするな、って話らしいね。納得はするけど、俺だったらそんな助言はしないなぁ、と思ったので書こうと思った次第。(このブログ、この手のスピリチュアルエンジニアリングの話多い気がする)

思い出そう

プログラミングを始めた時の自分を。
初めて画面に HELLO が表示された時、俺は 10 PRINT "HELLO" の意味なんて知らなかった。CPU がどうやって動いているのかも、そもそも CPU の存在すらも噂程度の知識でしか認識していなかった。メモリというものもあるらしい。ハードディスクというものもあるらしい。メモリとハードディスクの違いってなんなんだろう……。

その後

インタプリタの存在も簡単な実装も知って、CPU やメモリの存在や、動きも知った。なるほど、こうやって動いていたのか。なんだ、簡単じゃないか、はじめからこれを知っていれば簡単だったのに……。

誰かに教えたい

いずれ、こう思うようになる。ならないかもしれないけど。
そして教えるときに考えるんだ。「基礎から学んだ方が効率的だ」と……。

しかし

果たしてそうなのだろうか。意味もわからず座学を机上で学ぶことの苦痛さを忘れていないだろうか。
中には座学を嫌だと思わなかった人もいるかもしれないが、僕の(狭い)観測範囲では座学を楽しんで学んで実務能力を身につけたような人はいない。多くの人は、実際に手を動かして試行錯誤するほうが楽しいのではなかろうか。

まとめると

プログラミングを学ぶ流れは3つのフェーズに分けられると思っている。

  1. 本質ではなく振る舞いだけを追いかけてとりあえず使えるようになる
  2. 本質に興味を持ち、調べることでそれを理解する
  3. 本質にもとづいて、振る舞いを捉えられるようになる

フェーズ1と3は表面だけを見れば同じように見える。手戻りしているようにすら見える。しかしそれは違う。このような手順を追うからこそ、飽きずに学習を続けることができるのだ。
フェーズ1の存在を忘れてフェーズ2から学習を始めることを勧めるのは良くないと思う。

んで推察とか

フェーズ1を終えると、フェーズ3を終えた人と同等の技術があるかのように思えてしまうがそれは間違いなのだ。にも関わらず、フェーズ1を終えただけでフェーズ3まで終えた人と同等の技術力を主張する人がいる。
すると、それを嫌がって、(これも間違いなのだが)フェーズ1から学習を始めるなと主張する人がいる。
そういうことなんじゃないかなぁ。

ちなみに

自分はよく Node.js を使いますが過去に「Node.js ではフレームワークを使うな」という発表をニコニコ超会議1でやりましたが、それはまた、別の理由です。

**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 を実装してみてます。どうなることやら。