2010/12/19
らむ太の質問
- (初級): 「せっけんは、なにでできているの?」
- (中級): (水を浴槽の縁に滴らし、表面張力で盛り上がるのを示して) 「ほらほらみてみて。みずは、どうしてたかくなるの?」
- (上級): 「にんげんは、どうしてたっているの? ほねがあるから? きんにくがあるから? けっかんがあるから?」
Tag: 生活
2010/12/14
車輪の再々発明 - dd wrapper in Gauche
ddを子プロセスで起動してシグナル送ってprogressを見ようという話。 現実的には、 スクリプト書くならわざわざdd起動せんでも自前でコピーすればいいんだけど、 子プロセス制御のサンプルとしては実に手頃な課題と思った。 出力のサイズを求めるget-totalは弾さんのに準拠。
#!/usr/bin/gosh
(use srfi-1)
(use gauche.process)
(use text.progress)
(use file.util)
(define (main args)
(let ([total (get-total (cdr args))]
[proc (run-process `(dd ,@(cdr args)) :error :pipe)])
(sys-nanosleep #e5e8)
(unwind-protect
(doit proc total
(make-text-progress-bar :header "" :header-width 0
:max-value total :num-width 20))
(process-wait proc))
(process-exit-status proc)))
(define *sig* (if (#/linux/ (gauche-architecture)) SIGUSR1 29 #|SIGINFO|#))
(define (doit proc total bar)
(let loop ()
(sys-nanosleep #e1e8) ;0.1s
(process-send-signal proc *sig*)
(rxmatch-case (read-line (process-output proc 'stderr))
[test eof-object?]
[#/(\d+) bytes/ [_ c] (let1 cnt (x->integer c)
(bar 'set cnt)
(when (< cnt total) (loop)))]
[else (loop)]))
(bar 'finish))
(define (get-total args)
(or (and-let* ([m (any #/if=(\S+)/ args)]
[ (file-is-regular? (m 1)) ])
(file-size (m 1)))
(let ([bs (any #/bs=(\d+)/ args)]
[cnt (any #/count=(\d+)/ args)])
(* (or (and bs (x->integer (bs 1))) 256)
(or (and cnt (x->integer (cnt 1))) 1)))))
cookbook的なポイントはこのあたりかな:
- アーキテクチャによる切り替え。
(define *sig* ...)のところ。 - text.progressの使い方。
- 正規表現をpredicateとして使う。
(any #/if=(\S+)/ args)とか。
泥縄的な話:
doitを呼び出す前に0.5秒のwaitを入れてるんだけど。 これを入れる前に、ofで指定するファイルが既に存在してかなり大きい場合に ddがコピーせずに終了してしまう (終了コードは、シグナル10を受けて終了) という現象が起きた。dd単体でstraceしてみると、出力ファイルのopenが 終わった後でシグナルハンドラを設定してるんで、もしかすると open(...|O_TRUNC) でファイルをtruncateしてる間にSIGUSR1を受けて 終了しちゃうのかもしれない。*BSDならSIGINFOがデフォルトで無視されるから 問題無いと思うが…
Tags: Programming, Gauche
2010/12/12
マイナー言語でお仕事
これすんごくおもしろい。
実用規模で使ったときにどんな感じかなあ、っていうのは、 試しに触ってる時の感触と違うことが多いから、 複数言語のバックグラウンドを持つ人による現場での体験談はとても参考になる。
オフサイドルールについて:
もうおじさんはこれだけ行が離れると横の位置が同じかどうか目がチカチカしてわかりません。
この目のチカチカを避けるためか、どうか、出来るだけ間隙を狭くするために、Haskellプログラマーは無意識にワンライナーになります。例えば上の例だと 2 のケースをだらだらーと一行に書きたがるのですね。その結果、一行500文字の Haskellコードなどが産み出されるのです。
わはは。
Common Lisp書いてるとなぜかSchemeに比べて一関数がどうも長くなりがちで、 やっぱり木構造の次のノードが上下に離れて見づらくなる。 C-M-SPC C-M-\ による自動インデントと C-M-f C-M-b による移動で 確認してる感じ。これが完全自動で使えないとちょっと辛いだろうなあ。
Haskellのtype classによるオーバロードはかっこいいなあと思ってたんだけど、 強力な型機能と組み合わさると、意図しないコードでも型検査を通ってしまって 見つけるのが厄介なバグになる、意外な落とし穴、というにのはへぇ〜と感心。
基本的に強静的型付に慣れたプログラマの心は、型システムに依存しすぎているため、一旦型システムを突破してしまったこういうバグに対し非常に脆弱です。もし Haskell の型システムがここまで強力ではなく、IO a と [a] での >> の多重定義が無ければ、事前に型エラーとしてレポートされていたのですが…
最後の、Haskellプログラマは個人プレーヤーとして最適化されてるので 3人集まると船頭が山に登る危険が、というのはこれはLisp界でも とてもよく見られる現象だなあ。
Lispで仕事が出来たからって全てがバラ色になるわけじゃないってのもまた然り。 実用プログラムは泥臭い現実を相手にしてるんだから、 どんな言語で書いたって泥水の沼を進むようなものになるのは避けがたい。 ただまあ、沼に突っ込んでゆく装備にはいろいろあるよね、ってわけで。
Tags: Programming, Lisp, Haskell, OCaml
2010/12/08
Oh you need timin', Timin' is the thing
Y Combinatorの出資を受け、Web上のプレゼンツールを作ってGoogleにacquire されたZenterはひとつの典型的な短期勝負型ベンチャーの成功例だけど (cf. YC, Startup Life)、 その影で「aquireされなかった」側からの話 (via Hacker News):
オフィスソフトがWebに移行する時期、プレゼンツールだけが残されていて、 でも自分は先行していたし完成度も高く、そしてGoogleにも注目されていた。 そこからどうしてZenterに敗れたのかってのが「えっ、そんなことで」っていうような 理由なんだけど、こういう話自体は、ソフトウェア業界に限らず、珍しくはない。 当事者には飲み込むのが難しい話であろうけれど (上のブログの筆者は 冷静な筆致で書いているのがすごい。既に新しいことに挑戦しているから、 そういう姿勢が落ち着いた振り返りを可能にするのかな)。
ちょっとした運命のいたずらで人生が左右されるのは理不尽だけど、 それが人生というゲームのルール。 そこに救いを見るか絶望を見るかは人それぞれ。
Tags: YCombinator, Career

Comments (0)