2006/12/31

整数からなるリストを、指定した自然数の正値をスタートタグ、負値をクローズタグとみなしてグループにくくりたい。ただし、そのようなグループはリストは入れ子になっているかもしれない。

ようするに、こんなふうな結果を得たい。
gosh> test-list
(2 5 3 0 9 1 9 4 -1 9 4 2 1 0 1 9 -2 -1 5 1 -1 4 -1)
gosh> (group-between test-list 1)
(2 5 3 0 9 (1 9 4 -1) 9 4 2 (1 0 (1 9 -2 -1) 5 (1 -1) 4 -1))


condでグループにくくりながら再帰が基本的な戦略だけど、入れ子になっているかもしれないので工夫が必要になる。これには、一番内側にあるグループをくくり出すという操作を、指定した数がリストの表面に見えなくなるまで再帰すればよさそう。そこで、指定した数の正値が連続したら、いったんグループわけを始めたところに戻ってやり直すようにする。そこで call/cc ですよ。←関係ない(2007/5/18追記)
(define (group-between ls n)
(define (group-most-inner ls)
(cond ((null? ls)
'())
((eq? (car ls) n)
(call/cc
(lambda (k)
(let R ((first (list (car ls)))
(rest (cdr ls)))
(cond ((null? rest)
(error "pair unmatched" n))
((eq? (car rest) (- 0 n))
(k (cons (append first (list (car rest)))
(group-most-inner (cdr rest)))))
((eq? (car rest) n)
(k (cons (car ls)
(group-most-inner (cdr ls)))))
(else
(R (append first (list (car rest)))
(cdr rest))))))))
(else
(cons (car ls)
(group-most-inner (cdr ls))))))
(cond ((not (member n ls))
ls)
(else
(group-between (group-most-inner ls) n))))
これを応用して、XMLやHTMLの文書から要素を取り出してくるのに使えそう。構造だけ欲しければsxmlにしてしまえばいいけど、元の文書の「見た目」を変えずに特定の要素だけいじるときには役立つかも。

2006/12/29


男性の性欲は男性の自信と関係しているという説を最近きいたけど、ほんと? そういうもっともらしい意見を女性が信じちゃうと、性欲とかどうでもよくてとにかくかわいい女性が大好き、っていう人間が生きにくくなるので困るんですが。


みんな本当は性欲とかどうでもよくて、単純に女性と一緒にいると楽しくて、でも性的ないいわけがないと照れるから、しかたなく風俗とかいくんじゃないのか。風俗にいったことがないので推測しかできないけどさ、女の子どうしできゃっきゃって楽しそうにしてるのが羨ましくて羨ましくて、いっそのこと自分も女の子になって混ざりたいなあっていう男性の本音を歪めて提供するのがエロ産業なのではあるまいか。

2006/12/28


自転車のタイヤのバルブカバーを盗まれた。走行に支障はないとはいえ、腹がたつ。この手の犯罪はとにかくたちが悪い。やられ損だ。仮に犯罪が発覚しても犯罪者にとってたいした不利にならない。社会的なリスクも対して大きくないから、倫理感がない限り手を染めるほうが得策なんだろう。古今東西、不条理な大人の制裁がない社会で中高生がいきがるのは、これが理由にちがいない。

ハムラビ法展でさえ、たかだか受けた犯罪と同じ報復(懲罰)しか認めない。これはフェアじゃない。最初に目を潰された被害者のほうは、そもそももともと目なんて潰されたくなかったわけで、たまたま犯罪に合うようなことさえなければ幸せに暮らしていられたはず。一方、目を潰すほうには選択肢がある。相手の目を潰したところで高々自分の目を潰されるだけだから、それを覚悟して犯罪により得られるメリット(遺恨を晴らすとか)のほうが大きければ、犯罪のほうを選択できるわけだ。ずるい。

復讐法で対等に扱うべきなのは犯罪そのものの程度ではなく、犯罪により被る被害の程度であるべきだ。だって、仮に自転車のバルブを盗んだやつが僕の前に現れてバルブを返してくれた上に「俺の自転車のバルブをお前が盗んでもいいぜ」と言ってきたとして、僕はそいつの自転車のバルブなんて全然盗みたくないし、それで僕の今の憤慨とか悔しさはとうてい補填できない。かといって、そこでそいつを殴りつけて今の僕と同等の憤慨を感じさせることに成功しても、それで僕は警察に捕まって刑事裁判を受けて刑に服し、いま以上の不快感を味わうことになる。それじゃあやっぱり不公平だ。どうする?

ポイントは、法律にのっとった刑罰の度合が比較的線形に緩やかに厳しくなるのに対し、僕が相手に与えることが可能な苦痛はより急峻に厳しくできるというところにある。だって、そこでカッとなってそいつを殺害したところで、いまみたいな事情なら極刑にはなりそうもない。つまり、相手を殺害するまで至れば、確実に僕のほうが被害の程度が小さくなる。どのへんに損益分岐点があるかはさだかじゃないけど、妄想ではタコ殴りにして半身不随にするところくらいになる気がする。その程度であれば、こっちも懲役10年程度でかつ残りの一生を棒にふるだろうし、相手も一生を棒にふるだろうから、きっとイーブンだ。被害の程度を平等にするという精神にのっとればそれくらいが妥当だってことだ、ざまみろ。どんな犯罪も、せめてそれくらい殺伐とした覚悟でやってもらいたいものである。

頭に血が登っているので適当なことを書いちゃったけど、「自転車のバルブの盗難」を「家族の傷害事件」とかにしたら、それほどふつーの人情とかけ離れていないような気がしてきた。もし家族がそのへんのガキから傷害事件を被ったら、僕は犯罪者と被害の程度が同じになるようにがんばるかもしれない。


現代音楽は抽象的だといわれることが多い。だからわけがわからんと。確かにそういう面はある。


とりあえず何が現代音楽か定義せずに話をすすめるけど、クラシック音楽のいいところは、作曲家のほかに演奏家という存在がコンテンツのオーソリティーとして認知されていることだと思う。音楽を聴くほうにしてみれば、たとえ作曲家の言っていることが強烈すぎてちんぷんかんぷんでも、あるいは稚拙すぎて退屈でも、演奏家というフィルターを通して楽曲に接することができる。ようするに、どんな曲でも演奏家しだいでコンテンツとして成立できるってことだ。Pollini や Boulez を見れば、ここまではあながち間違っていないはず。ただし彼らの演奏が秀でているのは、それが一般人ウケするようなフィルターだからじゃなくて、譜面を読み込んで忠実な解釈を徹底していることにある。だから楽曲の質が大きく影響しているはずなんだけどつまらない曲もキラキラしちゃうから不思議。閑話休題。


彼らのすごさはおいといて、技術書というコンテンツも同じことが言えなくちゃだめだよなあと思う。譜面と演奏の関係が、原稿と編集の間に成り立つのか、それとももっとメタレベルで技術と書籍の間に成り立つのかは知らない。たぶん両方なんだろう。


2006/12/24

call/ccについておまえの知っていることを晒せと脅された。

まずこんな式を考える。
(begin 
(print "hello")
(print "goodbye")
(print "hello again")
(print "goodbye again"))
この式を評価すると、beginの中の環境で(print ...)という式が上からじゅんばんに評価される。結果的にこう出力される。
=>
hello
goodbye
hello again
goodbye again
Schemeでは、式の1つめの要素をオペレータとみなし、残りをオペランドとみなす。Schemeで式を評価するっていうのは、各オペランドを評価したものを引数として、それらをオペレータに適用することを意味している。

上記の例の(begin ...)という式を評価する場合、beginプロシージャに対してオペランドである(print ...)たちを評価したものが適用される。beginは引数として与えられた式を順番に評価していくプロシージャなので、まずどんな動作をするかというと、「(print "hello")を評価した。これから残りの(print ...)たちをbeginに適用する」。

で、この動作を記録にとっておくことにしよう。具体的にはスタックにつむことにする。
(print "hello")を評価した。これから残りの引数を評価する
同様に次の動作もスタックにつむ。
top    : (print "hello")と(print "goodbye")を評価した。これから残りの引数を評価する
bottom : (print "hello")を評価した。これから残りの引数を評価する
これを繰り返すと、beginの評価が終ったときのスタックの状態はこうなる。
top    : (print "hello")と(print "goodbye")と(print "hello again")と(print "goodbye again")を評価した。最後の式の値を返すよ
(print "hello")と(print "goodbye")と(print "hello again")を評価した。これから残りの引数を評価する
(print "hello")と(print "goodbye")を評価した。これから残りの引数を評価する
bottom : (print "hello")を評価した。これから残りの引数を評価する
じつはこの活動記録が「継続」を表している。で、スタックなので通常はいちばん上しか見えないけれど(つまり最後の式の値が返るだけ)、Schemeには途中を捕まえる方法がある。それがcall/cc。
(define c '())
(begin
(print "hello")
(print "goodbye")
(call/cc
(lambda (k) (set! c k)))
(print "hello again")
(print "goodbye again"))
こうすると、call/ccを仕掛けた場所の継続、つまり、くだんのスタックの下から2番目を捕まえて、あらかじめ適当な値で定義しておいたcに代入できる。けっきょくcには、「(print "hello")と(print "goodbye")を評価した。これから残りの引数を評価する」という継続が代入される。そこでcを評価すれば、cは「これから残りの引数を評価する」つもりでまんまんなので、こうなる。
gosh> (c)
hello again
goodbye again
これを応用すれば、たとえば「(a b a c a d)というリストから、最後のaで始まる部分リスト(a d)を取ってくる」とか、「木構造を探索するのに、途中で分岐した場所から別の枝を探索し直す」とかできる。これらは「途中を忘れて覚えておいた場所からやり直す」という人生やりなおし機型の応用といえる。一方、「とにかくcall/ccを仕掛けた場所に戻れる」という性質を利用すれば、いわゆる局所脱出ができるようになる。具体的な例はディヴィグの本とか"Seasoned Schemer"とかを参照。そもそもこの記事は"Seasoned Schemer"のオレ解釈なわけで。

2006/12/08

日本語の疑問文で「それとも」は、 or 条件だと見なしていいだろう。
Cさん:年賀状、出さないですよね? それとも出しますか?
Kさん:うん
出すか出さないかしかないので、この問題の答えは常に true だ。コードにすれば一目瞭然。
(define send-card? (lambda () #f))  ; 出さないつもりでも……
(or (not (send-card?))
(send-card?))

=> #t ; 答えは「うん」
ところが、実際にはこういう会話が成立する。
Cさん:年賀状、出さないですよね? それとも出しますか?
Kさん:いや(出さない)
なんで排中率を放棄して false を返しているのか。
それは鳥頭だからであって、ひとつめの質問を忘れちゃってるだけだよね。
(call/cc
(lambda (k)
(or (not (send-card?))
(k (send-card?))))) ; 忘れた

=> #t ; ???

どうして call/cc で脱出せずに #t が返るの?

2006/12/07


(define (trace ls)
(call/cc
(lambda (skip)
(let R ((ls ls))
(cond ((null? ls)
'())
(else
(call/cc
(lambda (k)
(set! trace (lambda () (k #f)))
(skip (car ls))))
(R (cdr ls))))))))


2006/12/04


本当は好きなものを嫌いと言ってみることでアイデンティティを成立させようとしていた時期があったと思う。

たとえばクラシック音楽への興味は、メジャーな楽曲のメジャーなフレーズへの興味から入って、そのうちマイナーな作品の魅力に気づき、オレだけが知っている的な優越感とともにどんどんマイナーな作家/作品/演奏を指向していって、そのうちメジャーな作家/作品を否定するようになった。このメジャー否定は、小中学校の音楽の時間に超メジャーどころを強制的に視聴させられて感想文を書かされるような体験と調和して増幅した。もう、なんでこんな子どもっぽい曲を聴かなきゃいけないんだ、と。モーツァルト? ヴェーベルンでも聴かせろや。

で、高校生にもなるとクラシックなんかよりハードロックに目覚めるから、モーツァルトもヴェーベルンも忘れさる。モーツァルトを思い出すのはずいぶん年齢を経てからだ。そこで、なんでこれを否定してたんだろうと思って悲しくなる。モーツァルトを否定することで、オレはもっとディープな作品を聴いているんだという優越感を安直に手に入れようとしていたんだろう。

今思い出すと、本当はモーツァルトも好きだった。好きなものを好きと言えるようになるには、たぶんものすごい跳躍が必要だった。どこで飛んだか知らないけど、いまは自分の好き嫌いを社会とのかかわりでとらえなくてすむ場所にいる。生きやすい。

なんで突然こんな個人的なことを書きたくなったかというと、フジテレビで月曜日に放映している「のだめカンタービレ」が楽しくてしかたないから。自意識を一周してきて、ようやくこういうドラマを素直に楽しめるようになったんだなあ。