2015/12/05
PC Upgrade Memo
家族用PCが不安定になってきたのでいくつかパーツを入れ替えた。
元はHaswellのPentium Dual Coreだったんだけど、息子がMinecraftで ヘヴィに使うようになってから時々画面がフリーズする。 電源がヘタってるのを疑っていたんだが 使ってるスリムケースが独特のフォームファクターで、 合う電源が既にディスコンになってたのだ。 (In Win IW-P240F1-0というやつ。TFXと書いてあるが外形がTFXと微妙に異なりネジ穴やコネクタ位置が合わない。ケース自体はネジ一本で簡単にばらせるんで気に入ってるんだけど。)
そこで余っていたATXのケースの方に移してCPUをCore i5に、 メモリも8Gに。このケースにはもともとCore2 Quadで組んでて Windows載せて専ら検証用に使ってたんだけどHDDが飛んで放置していたのだ。
空いたスリムケースの方は余り物を詰めて、こっちに改めてWindows入れて検証に 使うことにする。GaucheのMinGW版のパッチを色々頂いているのでさっさと進めなければ。
ついでにメインマシンのメモリを増やしたんだけど、ちょっとハマった。 空いてたDIMMスロットにメモリを足したらPOSTの最中に電源が切れちゃう。 接触不良、メモリ不良、色々疑って試してみたがわからない。そのうち元のとおりの メモリ構成でも同様の症状になってしまった。ちょっとあせる。
基本に戻ってHDDやシャーシの接続を全部外し、CMOSも念のためリセットして CPUも再マウントし、最低限のメモリだけで起動してみる。と、動く。 ひとつづつ接続を足して試してみたら、意外なものが犯人だった。 ケースのPower SWがいかれててONになりっぱなしになることがあり、 マザーボードがemergency shutdownしてたらしい。 今回、マザーボードにpower swがついていたので単独でテストできたから分離できた。
PCパーツの中ではケースが一番長持ちするんだけど、こういう可動部品は やっぱり劣化するのだな。このケースは確か2002年から使ってるんで無理もない。
Tag: PC
2015/11/20
UH Acting class
ハワイ大学でのKeo Woolford氏による8週間のintensive acting course終わり。モノローグひとつ、シーン4つ、オーディションシーン1つ、かなり濃いクラスだった。運転中にぶつぶつ台詞を練習する日々はしばしお休み。(車での移動は声を出しての練習にかなり使えるんだけど、東京やNYみたいに電車移動が中心だと大変そうだ。)
Keo先生のテクニックは非常に具体的・実践的であった。シーンワークではこれまで身につけたテクニックを応用してみて理解を強化することもできるし、やはりなるべく継続的にクラスは取るべきなのだろうなぁ。うーん。
もうひとつクラスの醍醐味は他の役者さんの創造の現場を見られることで、今回のクラスにはHawaii Five-0にセミレギュラーで出ているDennis Chun氏が参加してて彼のシーンを見られただけでもう授業料の元が取れたと思えたくらい。
最終的な作品に残ったものだけでなく、作る過程で「選ばれなかった」選択肢、検討の結果捨てられたものもまた、作品を形作っている。 (これはプログラムにも当てはまる。) でも最終的な作品に残ったものだけを見てては、選ばれなかった選択肢のことはなかなかわからない。メイキングの資料なんかで若干垣間見ることはできるとしても、本当のところは作る過程に参加するしかないだろう。
Tag: 芝居
2015/11/10
他人から作品についてのフィードバックをもらった時に、それを他人と自分のパワーゲームのようにとらえてしまう人がいるように思える。また、フィードバックすることをパワーゲームに利用しようとする人もいる。
フィードバックをもらうことは鏡を見るみたいなものだ (あるいは、自分の持ってない測定器で何か新しい指標を測るみたいなものだ) と思ってれば、パワーゲームになりようがない。観測結果が改善に使えるなら使えばいいし、使えなければ捨てるだけ。
ドラえもんの「うそつき鏡」みたいなものを手に入れて四六時中鏡ばかりに見入るようになってしまう危険もあるのでフィードバックに頼りすぎるのはまずいけど、より良いものを作りたいという目的さえ忘れなければ何とかなるんじゃなかろうか。
Tag: 表現
2015/11/03
勝手にお題---テキストフィルタ
こちらのblogでGaucheを使って頂いた:
メインロジック以外にコマンドラインオプション処理やエラーハンドリングなども入り わりと実用向けの良い課題になっていると思う。
メインロジックは上記blogより引用:
テキストファイルの先頭から指定したbyte数(または文字数)だけ出力し、改行を出力し、先頭から1byte(または1文字)シフトした位置から同じように出力し、改行を出力し、再びシフトし――ということをファイル終端まで繰り返すコンソールアプリだ。例えばこんな感じ。
$ echo -n abcd | hcasl -n 1 a b c d $ echo -n abcd | hcasl -n 2 ab bc cd $ echo -n abcd | hcasl -n 3 abc bcd
オリジナルのGaucheのコードも特におかしいというわけではないけれど、 面白い課題なので別解をステップバイステップで書いてみよう。
Step1. リストの先頭n個を取る
入出力は後で考えるとして、まずはリストからリストへの変換を考えてみる。 たとえばこんな動作をする関数だ。
gosh> (shift-slice '(a b c d) 2) ((a b) (b c) (c d))
リストの先頭n個を取るにはtake
が使える。素直に再帰でループを回すと
この通り。
;; バージョン1 (define (shift-slice lis n) (if (< (length lis) n) '() (cons (take lis n) (shift-slice (cdr lis) n))))
しかしこのコードには気になるところがいくつかある。
- 末尾再帰でないので、入力長Nに比例するスタックを消費する。
(length lis)
はO(N)の処理で、それをlis-n回のループで繰り返すから そこだけでO(N^2)だ。
最初の問題は教科書どおり、累積変数を導入して末尾再帰に書き換えることで解消できる。
2番目の問題については、最初のn個までしかリストをチェックしない
length<=?
という組み込み手続きが使える。
;; バージョン2 (define (shift-slice lis n) (let loop ([r '()] [lis lis]) (if (length<=? lis (- n 1)) (reverse r) (loop (cons (take lis n) r) (cdr lis)))))
以上は「リストの頭からn個取る、リストをずらして繰り返し」というアルゴリズムを 素直に実装したものだ。けれど、このアルゴリズムの入力と出力の関係を 静的に見てみると、別の考え方もできる。
入力(a b c d)、n=3の場合について考えよう。入力をひとつづつずらしたものを n個並べてみる。
a b c d <-- 入力 b c d <-- シフト c d <-- シフト
この図を縦に見ると出力が得られる。
a b c d <-- 入力 b c d <-- シフト c d <-- シフト | | v v 出力1 2
入力lisをひとつづつずらしたリストのリスト、は次の式で得られる
(drop
はリストの要素が足りないとエラーになるが、
drop*
だと足りない場合は()
になるだけなので今回は都合が良い):
(map (cut drop* lis <>) (iota n))
確認:
gosh> (let ([lis '(a b c d)] [n 3]) (map (cut drop* lis <>) (iota n))) ((a b c d) (b c d) (c d))
これだけ見るとリストがn個複製されてるみたいだけど、実際には
共通部分は共有されてるのでメモリ使用量は増えていない。そのことは
上の式の直後に結果をwrite-shared
してみればわかる。
gosh> (write-shared *1) ((a . #0=(b . #1=(c d))) #0# #1#)#<undef>
#0=
などはその部分が共有されてるということ。最後の#<undef>はwrite-shared
の戻り値。
一方、 リストのリストに対して「その先頭だけを集めたリスト」「2番目を集めたリスト」… というリストを作るのはこう書ける:
(apply map list <リストのリスト>)
リストのどれかの要素が使い尽くされるとmapが終わるので、出力の長さは 入力リストの一番短いものに揃う。
gosh> (apply map list '((a b c d) (b c d) (c d))) ((a b c) (b c d))
合わせると次のとおり:
;; バージョン3 (define (shift-slice lis n) (apply map list (map (cut drop* lis <>) (iota n))))
Step2. 入力と出力とlazy sequence
課題では、入力は標準入力やファイルから取られるのでかなり長くなる可能性がある。 また、出力の長さも入力長に比例する。処理に必要なデータサイズはnで限定されるのに、 一旦全てのデータをメモリに置かなければならないとしたら何か無駄っぽい。
でもlazy sequenceを使えば、リストを使っている気分で、必要なところまで計算する ことが出来る。
例えば、port->char-lseq
を使うと、ポートから読んだ文字のリストが得られる。
ただし文字は必要な部分までしか読まれない。次の例ではtake
で最初の10要素
だけ取ってるので、それ以降のファイルは読まれない。
gosh> (call-with-input-file "/usr/share/dict/words" (^p (take (port->char-lseq p) 10))) (#\A #\newline #\A #\' #\s #\newline #\A #\A #\' #\s)
(注:port->char-lseq
は0.9.4リリース以降に入ったので、
0.9.4を使う場合は次のとおり定義してほしい。ついでにバイト単位のport->byte-lseq
も
示しておく。)
(define (port->char-lseq :optional (port (current-input-port))) (generator->lseq (cut read-char port))) (define (port->byte-lseq :optional (port (current-input-port))) (generator->lseq (cut read-byte port)))
入力をlazyに読むのはこれを使えば良いとして、出力をlazyに生成するには
先のshift-slice
にもうひとつだけ工夫が必要だ。map
は貪欲で
入力リストを全部食べて出力を生成する。これをlmap
に変えるだけで、
出力はlazy sequenceになり、必要に応じて計算されるようになる。
(内側のmapは変える必要がない。このmapの入力はn個の整数に決まってるから。)
(use gauche.lazy) ; lmap ;; バージョン4 (define (shift-slice lis n) (apply lmap list (map (cut drop* lis <>) (iota n))))
入力をポートから取り、出力をcurrent-output-portに出して要素ごとに 改行するのは次のとおり書ける:
(define (process-1 port n) (dolist [r (shift-slice (port->char-lseq port) n)] (for-each write-char r) (newline)))
テスト:
gosh> (call-with-input-string "abcd" (cut process-1 <> 2)) ab bc cd ()
最後の()はdolist
の戻り値。
Step3. 複数の入力、出力先の変更
実用的なコマンドでは、入力や出力がコマンドライン引数によって 様々に変わり得る。
- 複数の入力が指定された場合、それらを順に処理する
- 入力はファイル名指定、もしくは "-" の場合は標準入力
- 入力が指定されなかったら標準入力
- 出力は無指定もしくは"-"なら標準出力、そうでなければファイル名指定
いっぺんに全部やろうとすると条件がごちゃごちゃするので、 レイヤに分けてゆこう。まずは複数の入力の処理。 「入力が無い場合は標準入力」についてはcaller側でcurrent-input-portを 補ってやることにする。
もう一つ、元の仕様では、
- 途中でエラーがあった場合はエラーメッセージを標準エラーに表示しそのファイルをスキップして 実行を続ける
- 途中でエラーが起きたかどうかを最終的に知りたい
というのがあるようなので、foldでループしてエラーコードを持ち回る。
;; inputs - ポートもしくはファイル名のリスト ;; return - 0 on success, 1 on error (define (process-multi inputs n) (fold (^[in c] (guard (e (format (current-error-port) "~a\n" (~ e'message)) 1) (cond [(port? in) (process-1 in n)] [(equal? in "-") (process-1 (current-input-port) n)] [else (call-with-input-file in (cut process-1 <> n))]) c)) 0 inputs))
最後に出力でのディスパッチ。output
は -
もしくはファイル名。
(コマンドラインでのoutput省略時は、コマンドラインパーザ側で-
をデフォルト値に
してやれば良い)。
(define (hcasl n inputs output) (if (equal? output "-") (with-output-to-port (current-output-port) (cut process-multi ifiles n)) (with-output-to-file output (cut process-multi ifiles n))))
コマンドライン引数処理などを含めた全コードはこちら:
(https://github.com/eel3/hcasl からの派生物なのでライセンスは本家に準じる)
Tags: Gauche, Programming
2015/11/01
上手下手ではなく
ここ数日の翻訳の話で「叩き台に達しないレベルがある」と 書いた点について、自分の翻訳はレベルに達していないのではないか、 しかし誰かに見てもらうにしてもそういう人の時間を取ってしまうのは迷惑なんじゃ ないか、と心配になる向きもあるようだ。
大丈夫。何も翻訳レビューとか翻訳指導を頼むわけじゃない。 「これを叩き台としてみんなで改善してゆきたいのだが、可能だろうか」だけを聞くんだ。 それなら、原文を読んだことのある人は、1~2ページ読むだけで答えられる。
そう、分かる人ならたかだか10分程度で判断できる、その程度の話なのだ。 (それ以上読み込まないと判断できないようなら、多分叩き台としてのレベルはクリアしてる。)
上手い人が「下手糞は引っ込んでろ」と言うのとは違う。 むしろ上手下手という評価に載せる以前の話だ。 このチェックをクリアできないというのは、 ゴールに向かって走るはずなのが、全然見当違いの方向に走っちゃってる、とでも言おうか。
どうしてそうなるんだろう。仮説をふたつ考えた。
- 作業者は、作品の質に関心が無い。より良い作品を出すこと以外の何かを目的としている。
- 作業者は、何をどうしたらよいのか本当にわからない。わからないなりに独断で どんどん進んだ結果ゴールとはかけ離れたところに到達してしまった。
1は、作業者にある種の悪意---何かを積極的に潰すという悪意ではないけれど、 関心の不在、愛の不在によりなされる悪がある---を仮定せざるを得ない。 オリジナル作品ならば、それでも悪は作品だけに及ぶので特に問題はないが、 翻訳の場合は影響が原著の内容に及ぶ(翻訳しか読めない人にとっては、 翻訳の評価が原著の評価となる)ので大変にまずい。
しかしハンロンの剃刀により、私自身は2の仮説を支持したい。 誰だって、知らない分野については最初はcluelessなのだ。 (いや、知ったつもりになってて実は知らなかったとわかること、もたくさんあるので、 実はどんなレベルの誰にでも起こり得ることではある。) そう思って一連のエントリを書いた。
もし一連のエントリを読んで、自分の翻訳を出していいのか自分で判断できないと 思った人がいたら、私の詳しい分野については私に尋ねてくれて構わない。 尤も、コンピュータサイエンスやプログラミングの分野に限っても、 私の知らない分野はたくさんあるので、判断できない場合もあるだろう。 別のお勧めとしては、その分野のコミュニティで尋ねてみることだろう。
(1の場合だったとすると、作業者はそういう心配さえしないだろうから、 一連の文章は届かないだろう。それは仕方ない。 ただ、読者の方に良い判断を期待したい。出てきたものに対して誰かが 叩き台にすら乗らないと評したなら(そしてあなた自身で判断できないのだとしたら)、 その成果物は明後日の方向に行っちゃってる可能性がある。 他の人の訳と比べるといったこと自体がナンセンスなのだ。)
ちょっと面白いなと思ったこと。 ナイーブに考えると、閉じた関係の中で晒すより 不特定多数に晒す方が勇気がいると思うんだ。 友人の前で演奏するのと往来で演奏するのでは後者の方がはるかにおっかない。
ところが「ネットの不特定多数」だとこれがむしろ逆転する。 閉じた関係は下手を打つと失われる可能性があるけれど、 ネット上のランダムな関係なら失われても構わないからか。
でも、成果物に対する愛があるなら、少しだけ、恥をかく勇気を出して、 顔の見える人に評価を仰いでも良いのではなかろうか。 多分、思っているよりハードルは低いよ。
Comments (0)