Island Life

2006/12/25

12/22のrangeジェネレータだが、ジェネレータと範囲を取ってジェネレータを 返す方が綺麗だな。

(define-constant *eof* (read-from-string ""))
(define (eof) *eof*)

(define (generator-range begin? end? gen)
  (define next #f)
  (define (in)
    (let1 elt (gen)
      (cond ((eof-object? elt) (set! next eof) *eof*)
            ((end? elt) (set! next out)))
      elt))
  (define (out)
    (let1 elt (gen)
      (cond ((eof-object? elt) (set! next eof) *eof*)
            ((begin? elt) (set! next in) elt)
            (else (out)))))
  (set! next out)
  (lambda () (next)))

これで

gosh> (with-input-from-process "w3m -dump_source http://www.yahoo.com"
        (cut port-for-each print (generator-range #/^<style/ #/<\/style>/ read-line)))
<style type="text/css">
a{color:#16387c;}
a:link,a:visited{text-decoration:none;}
a:hover{text-decoration:underline;}
</style>
<style type="text/css" media="all">
#p{width:310px;}
form{margin:0;}
</style>
#<undef>

こうなる。

Tag: Gauche

2006/12/24

6行でプレゼント交換(最高にキモい Scheme コードを書いてみよう)より:

(use srfi-1) (#0=begin (#1=define-macro(oa . l)`(#0#,@(map(#2=lambda(x)`(define-method object-apply((l <list>),@(car x)),@(cdr x)))l)))(#1#
(dn s p)`(#0#,@(map(#2#(a b)`(define ,a ,b))s p)))(dn(d fn dl fc p! !p fm f- e? rv mm fl nl l/)(define #2# delay force push! pop! format filter-map
equal? reverse member fold newline let/cc))(oa(((i <integer>)) (list-ref l i)) (((s <symbol>)) (null? l)) (() (cdr l)) (((f <procedure>))(map f l))))(d 
!())(d(_ \>)(if[\> 'n](%)(l/ c(p! !(dl(c(_[\>]))))[\> 0])))(d %(l/ c(fn()(if[!'n](c '@)(fc(!p !))))))(d(pp l)(fl(fn(e _)(fm #t"~a->~a "(#1=[e car] 0)(#1# 1)))
(nl)l))(d(? x)(x(fn(e)(f-(fn(h)(if(or(e? e h)(e?[e][h]))#f`(,e ,h)))x))))(d(\ x r)(if[x 'n](pp(rv r))(\[x]`(,@r ,(let1 t (_ [x 0])(if(mm[t 1][r cadr])(%)t)))))
(%))(\(?'((a1 . a)(a2 . a)(b1 . b)(c1 . c)(d1 . d)))'())

すげえ。シンボルに#n=記法を使って記述量を減らす手法は気づかなかったわ。

シンボルにバックスラッシュ \ を使えるかどうかは未定義なんで、そこだけ 置き換えた方がいいかも (R5RSでは使えない、Common Lispではエスケープ文字、 Gaucheではどう扱おうか迷ってる)。

Tags: Programming, Gauche

2006/12/22

フリップフロップのように動作する演算子、/regexp/../regexp/。 awkの似たような機能はずいぶん使ったのでこれが便利であることは分かってるが、 隠された状態が色々あって気持ち悪い。同様の機能を、状態をうまく閉じ込めて実現 するとどういったAPIになるだろうか、とつらつら考えていて、ジェネレータを 扱う関数群としてまとめられるんじゃなかろうか、と思った。

ここでのジェネレータは単なるthunk (引数無しの手続き) で良い。呼ばれるたびに次の データか、もしくはデータが無くなれば#<eof>を返すとする。無限にデータを生成 してもいい。標準入力関数のreadやread-charはそのままジェネレータとして使える。

そうすると、このジェネレータの出力に対してfold, map, for-each, take, drop など、ストリームやシーケンスと同型の関数群が定義できるだろう。例えば:

(define (generator-fold proc seed gen)
  (define (rec seed)
    (let1 elt (gen)
      (if (eof-object? elt) sedd (rec (proc seed)))))
  (rec seed))

(define (generator-take gen k)
  (define (rec k)
    (if (<= k 0)
      '()
      (let1 elt (gen)
        (if (eof-object? elt) '() (cons elt (rec (- k 1)))))))
  (rec k))

無限要素を許すこと、必要なだけ値を生成すること、等は遅延ストリームと よく似ているが、ジェネレータはリスタートが出来ない(途中状態をcall/ccで 捕まえておいてそこから再実行をかけることが出来ない)。ただ、それは 状態を保存しておかなくても良いことを意味し、効率は遅延ストリームよりも 良くなる。

ジェネレータを使うなら、フリップフロップ演算は一つのジェネレータからの データの流れをふたつのデータの流れに振り分ける弁みたいなものになるだろうか。

(define (generator-range gen begin? end? in-proc out-proc)
  (define (out e ins outs)
    (cond ((eof-object? e) (values (reverse ins) (reverse outs)))
          ((begin? e) (in (gen) (cons (in-proc e) ins) outs))
          (else (out (gen) ins (cons (out-proc e) outs)))))
  (define (in e ins outs)
    (cond ((eof-object? e) (values (reverse ins) (reverse outs)))
          ((end? e) (out (gen) (cons (in-proc e) ins) outs))
          (else (in (gen) (cons (in-proc e) ins) outs))))
  (out (gen) '() '()))

ジェネレータgenからの流れを、in-procかout-procへと振り分ける。一応、 関数的に、副作用を当てにするのではなく結果をリストでそれぞれ収集してみた。

gosh> (with-input-from-process "w3m -dump_source http://www.yahoo.com"
        (lambda ()
          (values-ref (generator-range read-line #/^<style/ #/<\/style>/
                                       identity identity)
                      0)))
("<style type=\"text/css\">" "a{color:#16387c;}"
 "a:link,a:visited{text-decoration:none;}" "a:hover{text-decoration:underline;}"
 "</style>" "<style type=\"text/css\" media=\"all\">"
 "#p{width:310px;}" "form{margin:0;}" "</style>")

こういうの、util.generatorとかしてモジュールにしとくと何か使えるだろうか。

Tag: Gauche

2006/12/19

内田樹の研究室: 創造的労働者の悲哀

しかし今、労働は創造となった。
そのせいで仕事をする人々はその定義上、仕事をつうじて絶えず自己実現の愉悦と満足にうちふるえていなければならなくなった。
苛酷な条件である。
絶えず創造し続け、絶えず快楽にうちふるえていなければならないという重圧に耐えかねた創造的労働者たちの中から「自分らしい作品ができないくらいなら・・・」と沈黙と無為の道を選ぶようになる者が出てきても怪しむに足りない。
ニートやフリーターはこの「創造的労働者」の末路である。

「創造」や「芸術」といったものが、相変わらず、ひどく誤解されていることが 不幸の元であるのかもしれない。三木清が言うように、岡本太郎が言うように、 芸術は生活の中にあるものではなかったか。 それは生活を楽しむ技術(三木)であり、自由を取り戻す手段(岡本)ではなかったか。

生活に密着した自分自身のこととしてではなく、人が創るものを端から眺める だけで創造やら芸術やらをとらえていると、 ユニークでなければならないとか、人と違っていなければならないといった ことばかりに目が行く。でもそれは「結果としてそうなることもある」という だけのことで、そこばかり見るのは順序が逆だ。 繰り返す日常自体を楽しむ技術を見出した時、結果として日常が他人から見て ユニークになるのだ。

これは「個性」にまつわるアンビバレンツとも関連している。 社会的には人と同じであるべきという強烈な暗黙のプレッシャーがあるくせに、 建前では「個性を伸ばす教育」などと言っている。 個性というのはもうどうしようもなくそこに有ってしまうもの、 逃れようもない自分自身のことで、伸ばすとか育てるとかいうものではない。 抑えたり制御したりすることしかできない。 (昔、同じことを書いたことがあるが、子供を持ってみて改めてそう思った)。 全く抑えないと社会として収拾がつかなくなるから、 学校で個性を適度に抑える技術を学ばせるのは間違ったことではない。 でも今は、個性を徹底的に抑え込むせいで、「個性的」という言葉さえ いくつかの類型的なモデルを指す言葉になってしまったきらいがある。

自分ではない、メディア等で流布される特定の人物の生活を、それこそが クリエイティブで個性的な生活だと勘違いしていれば、そりゃ 自分自身が「創造的」「個性的」に生きるのは難しかろう。 他人の人生を生きようとしてるわけだから。

* * *

もっとも、労働者を取り替え可能な部品として扱った方が 収益が見込めるという構造があった場合、経営者側が それを利用するというダークサイドに堕ちることは十分にあり得る。 そのような職場で生活を楽しむのはとても難しいだろう。 「自由を取り戻される」ことは経営者側にとっては不都合だから、 そうさせないような有形無形のプレッシャーがあるはず。

「とにかく働け」と言うことの問題は、そういう環境で しゃにむに働いた場合、自己実現どころか利用されるだけに なりかねないことだ。1世代以上前ならどこも似たようなものだったので その場で闘うことが自由への道だったのだろうけれど、 仕事が多様化した今となってはその場を去るって選択肢も ありだと思う。

でも一方で、どんなに「自分に合った」仕事であっても、日常で やっていることの95%は泥臭い、本質とは一見関係無いような 作業であるのが普通で、表面的な作業の無意味さだけを見ていると その仕事の「おもしろさ」を見損なう危険がある。で、 そういうことを嗅ぎわけるには、やっぱり「とにかく働いてみる」 経験が必要だったりする。

Tag: Career

2006/11/25

らむ太語録。

  1. 「あいやいや」 - 嫌だ
  2. 「あいた」 - 痛い
  3. 「ないない」 - 片付けています
  4. 「め〜」 - 目
  5. 「み〜」 - 耳
  6. 「っち」 - あっち
  7. 「った」 - あった
  8. 「っしょ」 - よいしょ
  9. 「っぱい」 - おっぱい
  10. 「ぶぅ」 - おぶう (湯冷まし、お茶)
  11. 「ぶ〜」 - 自動車
  12. 「ぅ〜〜」 - 救急車、消防車、パトカー
  13. 「びぃ」 - ビデオ
  14. 「ごー」 - Go、もしくは「私を外に散歩に連れていきなさい」
  15. 「し〜」 - 「私は尿意を催しているようです」もしくは「あちらで粗相をしてしまいました、後片付けをお願いします」
  16. 「ばいばい」 - 別れの挨拶、もしくは「私は一人で遊びたいのでどこかに消えて下さい」

Tag: 生活

More entries ...