Island Life

2017/02/02

Gaucheでひらけ!ポンキッキ (文字列の回転)

流行りに乗る

円環状につなげてずらして切り出すには、循環リストを作るという手もある。

(use srfi-1)
(define (rot s)
  (let1 l (string-length s)
    ($ for-each ($ print $ list->string $ (cut take <> l) $ drop
                   ($ circular-list $* string->list s) $)
       $ iota l)))

($ f $ g $ h $) はパイプを逆さにつなげたように読むと良い。データが右から入って左に流れてゆく。

gosh> (rot "ひらけ!ポンキッキ")
ひらけ!ポンキッキ
らけ!ポンキッキひ
け!ポンキッキひら
!ポンキッキひらけ
ポンキッキひらけ!
ンキッキひらけ!ポ
キッキひらけ!ポン
ッキひらけ!ポンキ
キひらけ!ポンキッ
#<undef>

Tags: Programming, Gauche, Scheme

2016/12/29

100 Rejections

今年は、学生映画も商業も全部ひっくるめてだけど、14回オーディションを受けた。 LAやNYでやってれば週2回とか受けるそうだから、 それに比べれば全然たいしたことはないけれど、 自分的には年間最多記録である。


こちらでオーディションを受け始めて落ちつづけてた頃、 「100回落ちるまでは諦めずに続けてみよう」と思った。 幸い数回に1回くらい拾ってもらえるようになって、 じゃあ年数回くらいのペースで受けてれば年1回くらい何かやれるかな、 てな感じで気が緩んでいたのだが、 「年間100回落ちることを目指せ」という記事を読んで考えを改めた。

In late 2011, a writer friend was sharing her experiences of having months of uninterrupted writing time at her residencies at the Millay Colony, Ragdale, and Yaddo. I was staggered by her impressive rates of acceptance.

[...]

I asked her what her secret was, and she said something that would change my professional life as a writer: "Collect rejections. Set rejection goals. I know someone who shoots for one hundred rejections in a year, because if you work that hard to get so many rejections, you’re sure to get a few acceptances, too."

これは作家の話なんだけど、すごく成功しているように見える作家の友人に秘訣を聞いてみたら、 「不合格/不採択/ボツ通知を集めるの。目標数を決めてね。年間100回落ちることを目指してる人を知っているけれど、それだけ頑張って落ちようと思ったら、そのうちいくつかは受かっちゃうわけ。」

生涯で100回なんてぬるかったっすね。毎年100回かあ。 あらゆるチャンスを、どんなに可能性が低くても、捕まえるつもりでいないと難しいだろう。

でも、落ちることで目標に近づく、と考えると、挑戦へのハードルはちょっと下がる。

落ちてもいいからと何も準備をしないで受けまくる、というわけじゃない。 少なくともオーディションについて言えば、 いい加減な準備で受ける方が万全の準備で臨むよりもうんと恐ろしいことなので、 必然的に準備はするようになる。


で、 エージェント経由でのオーディションは時の運だし増やしたくて増えるもんでもないので、 オープンオーディションで必ずしも自分のタイプと一致しなくても、 あるいはリモートでのプロダクションへのビデオオーディションとかでも、 とりあえず受けるようにしてみた。

100回にははるかに及ばないが、 オーディションの頻度が上がることで、変わってきたことがある。

オーディションは自己顕示ではなく作品発表の場、と割りきれるようになり、 何を準備してゆくべきかが明確になったことだ。

映像系のオーディションでは、1〜2シーンをあらかじめ受け取り、 それを演じるのが一般的だ。1次審査では相手役の台詞をADさんとかが読んでくれて 一人で演じる。2次審査(callback)がある時は、他の役者との絡んで演じることもある。 併せてモノローグを演じることもある。

どっちにせよ、シーンを演じるわけだから、 普段のアクティングクラスと同様に、シーンを創ってゆけば良いのだ。 アクティングクラスの場合は事前に相手役とリハーサルできることがあるから若干事情は異なるが、 リハーサルをやる直前の状態までは自分で持っていけるわけで、 その手順は普段の準備と何ら変わらない。 台詞を入れて、シーン分析を行い (superobjective・objective・obstacle・"the moment before"の同定、 substitution・inner object・actionの選択)、 シーンを成立させるところまで作っておく。 この準備過程は、やればやるだけ上手くなってゆくので、 オーディションもその機会だと思えばいい。

それを見て向こうがどう判断するかは向こう次第で、 自分の力の及ぶところではないから気にしても仕方ない。 たとえ素晴らしい演技が出来たとしても、 それが向こうの考える作品にフィットするかどうかは別問題だから。 ただ、自分が作って行ったシーンを人前で演じてみせる、という経験は確実にひとつ積み重ねられる。

こう思い始めたら、オーディション後の振り返りも別の意味を持ってきた。 以前、オーディション後に「あそこはああすれば良かった」などとくよくよ考えてもダメと書いたことがある。 それは変わっていない。 オーディションの場で起きたことについて後から別案を考えることに意味はない。 けれども、準備は足りていたか、結果としてシーン中にどこまでtruthfulになれたか、 という点について振り返り、次の準備へと反映することはできる。 substitutionは自分の中ではっきりしていたか、 the moment beforeを忘れていなかったか、 相手にreactできていたか、このへんの振り返りは、 アクティングクラスでシーンを演じた後の振り返りと全く同様だ。

舞台系のオーディションでは脚本全体が対象でどこを演じるかを事前に知らされないので、 完璧に準備してゆくのは難しい(未出版作品だと、契約の都合上脚本の持ち帰りも出来なくて、 劇場に行って目を通すだけ、ということもある)けれど、やれるところまで分析しておくことはできる。

最近は自分でシーンを録画して送る、self-tape auditionも増えてきた印象がある。 今年は4つやったかな。 オーディションの話が来てシーンの脚本を受け取ってから締切りまで36〜48時間しかないこともある。

脚本を受け取ったらまず、相手役を確保する。写るのは自分だけだけど、 相手の台詞へのリアクションは非常に重要なので、 カメラの向こうで生身に人間に読んでもらうのが極めて有効だ。 役者仲間には、 仕事の昼休みに手伝ってもらったりとか、色々世話になった。 感情的なシーンだと、静かな場所の確保も必要になる。 段取りをつけて、自分の演技の準備もして、効率的に撮影し、編集して送る。 これも回数をこなせばそれだけ練習になる。

10月にハワイ島で撮影した映画もこの形式のオーディションだった。 10/9の夜にエージェントから「明後日の午前中までにオーディションビデオ出して」と言われて大急ぎで段取りつけて翌朝撮影。 1週間後の10/17に「あなたを使いたいんだけど5日後から10日間ハワイ島に来れる?」と連絡があって、 慌てて仕事のスケジュールを調整した。 映画は来年公開予定。 3シーンくらい出演してる。カットされてなければ。


さて明日も撮影なので準備せねば。

Tag: 芝居

2016/12/28

批評の受け止め方

ネットに初心者が公開したプログラム等の成果物にあんまりツッコミが入ると萎縮しちゃうんじゃないか、という話が上がってた。

何かを表現することの初期段階に、 安全な環境で批評を受けるのは重要だ。たとえ Don't take it personallyと言われても、 意識的に自分と自分の作ったものを分けて考えるのは(最初のうちは)難しい。

ただ、ツッコミにもいくつか種類があって、 それを全部「不寛容社会」のせいにするのも乱暴すぎる。


成果物(ここではプログラム等)に対するツッコミの目的は、いくつかに分類できる。 複数の目的が混じっている場合もあるが、ツッコミを読み解くことで、そこに込められた 情報を目的別に分離できる場合が多い。

  1. 成果物自体の改善を目的とするもの: 最終的に、指摘が成果物に反映されることを期待するツッコミ。 バグの指摘、アルゴリズム上の問題、運用上の落とし穴の解消、等。 具体的な修正案やパッチの形を取ることが多い。
  2. 読者への情報提供を目的とするもの: 検索して訪れた読者が情報をそのまま流用するとまずいことが起きる可能性があるため、 そういう読者への付加的な情報を提供しようとするもの。 作者が本文を変更して注意書きを足してくれるに越したことはないが、 コメント等で読者の目に触れるようになっていればいい。
  3. 作者の行動を変えることを目的とするもの: 作者に一歩進んでほしいという建設的なものも、 その程度の意識で出てくるなといった非建設的なものもある。
  4. 突っ込む側の自己満足: 自分の優位性を誇示するマウンティング目的とか、 自分が押すフレームワークやら言語やらの布教目的とか。

個人的な印象では、エンジニア界の手斧の投げ合いの結構な割合は1や2だと思う。 コードが良くなることや、誤った情報が広まらないことが重要であって、 誰が書いたかとか誰が指摘したかはどうでもいい。 とはいえ、3や4も混ざってなくはない。

一方、作者の方の目的も色々だ。 成果物を晒してブラッシュアップする、というのが目的とは限らない。 初めて書いてみてうまく動いたからやったー!っていう気持ちをシェアしたいだけかもしれないし、 勉強を続けるモチベーション維持のために経過報告をしているだけかもしれない。

作者の目的と指摘者の目的が食い違っている時に、摩擦が生じる。


公開する以上、不特定多数からのフィードバックが集まるのは仕方ない。 作者の側として、次のことをまず前提にするといい。

ツッコミを受けとるか流すかは、作者の一存で決めることである

こう書くと当たり前のようだけど、何か言われたら影響されちゃうのも人間の性である。 けれど、「影響されるかどうかを決めるのも、自分の一存」なのだ。 明後日の方向に突っ込んでる無価値な批評はいくらでもあり、 そんなのをいちいち相手にする必要はない。 自分の目的にとって役に立つ批評だけより分けて使い、後は捨てればいい。

その前提を置いた上で、寄せられたツッコミのカテゴリにより対応を変える。 (混ざっている場合は要素ごとに分離して考えれば良い)

  • 突っ込む側の自己満足 - 無視する。
  • 作者の行動を変えようとするもの - 「この人の言うことなら聞いていいかも」と思える場合は取り入れる。それ以外は無視。
  • 成果物の改善 - 成果物を今後も使うつもりでメンテしていきたいなら取り入れよう。 でも、自分ではサンプルや練習のつもりで、それ以上改善する意図が無い時にこれが来たら、 その旨説明してお引き取り願うのが良かろう。 最初からそう説明してたのに指摘してくるのは無視でいい。
  • 読者への情報 - これは自分の問題ではなく、自分が書いたものを読む不特定多数の利益に関することである。 間違ったり誤解されやすい情報を広めることが本意でなければ、 その事実が読者の目に触れるようにしておくのが良いだろう。

だいたいにおいて、突っ込む側には「何かを変えたい」というモチベーションがある。 その変えたいものが、自分が変えたいものと一致するなら、指摘を利用すればいいし、 そうでないなら受け流せばいい。 相手のゲームに乗る必要はない。 自分のサイトで発表したなら、ゲームのルールを決めるのは自分だ。

Tags: Programming, 表現

2016/12/23

トランプのヤバさ

珍しく政治ネタ。4年後に読み返して杞憂だったなと思えることを祈りつつ。

大番狂わせの大統領選から1ヶ月半。 今週頭には選挙人投票があってトランプ次期大統領が正式決定した。 ひととおり選挙の分析が出た後、 リベラル勢からは、 ここからどう立て直してゆくかについての戦略や決意表明が次々に出ている。 (例えばBruce Schneier, これからの四年間における私の優先事項, yomoyomoさん訳)。 私の観測範囲にリベラルが多いせいもあり、皆が闘いに備えているような張り詰めた雰囲気を感じている。

でも、日本の報道や反応を見ていると、 「選挙戦では極端なことを言ってたけど、それ以外の公約にはまともなこともあるし、 いざ大統領になれば変わるんじゃないか」 「トランプ一人で何でも出来るわけじゃない、無茶な言動は優秀なスタッフが何とか止めるだろう」 みたいな楽観的な感覚もあるようだ。 トランプが過激な発言をするたびにリベラル系メディアが騒ぐのを、過剰反応しすぎじゃないの、 と感じている人も結構いるんじゃないか。

個人的には、ものすごくヤバい、と感じてる。

でもそれは、トランプの差別的発言とか、表現の自由への脅威だとか、 核武装強化発言だとか、そういう個々の動静ではない。

最近、トランプの側近の一人が 「彼(トランプ)の発言は文字通り(literally)取るんじゃなくて、象徴的に(symbolically)取るべき」と発言した。この一言にヤバさが集約されている。それを無邪気に側近が言ってしまうのがさらにヤバい。

実際、「国境に壁を作り、費用はメキシコに払わせる」とか「不法滞在外国人を全員追放」とか、 熱狂的支持者はともかく、大部分の人は文字通りそれを実行できるとは思ってなくて、 こういうのはキャッチーな煽りだと思ってるだろう。トランプはそういう煽りでメディアをひとしきり 賑わせた後で「やっぱやらないかも」「文字通りそういうことをやるという意味ではない」みたいに トーンダウンしたりする。裏付けの無いニュースや明らかに事実と反する情報を平気で流すこともやる。 要するに具体的な中身よりも、どう周囲が反応するかの方を重視している。 その点に関しては、かなり計算高い人物だと思う。

これが続くとどうなるか。

過去の発言に関して突っ込まれたら、 「あれは象徴的な意味で言ったのだ」といつでも逃げられる、ということだ。 言葉に対して責任を負わなくても良くなる、ということだ。

そして周囲も、毎回毎回の煽り発言に釣られるのにだんだん疲れてきて、 「彼はそういう人だから」で流すようになる。 で、発言が文字通り解釈できないから、 その発言が象徴するところの意味を忖度して周囲が行動するようになる。 トランプの意向に反する、と周囲が思う行動があれば、 先回りしてそういうのを抑圧するようになる。

でもトランプは具体的にそうしろという指示を出したわけではない。 行き過ぎがあれば「部下が勝手にやったこと」でその部下を切ればいい。 黙認していれば部下は承認されたと解釈して同様の行動を強化してゆく。 皆が、明示されない一線を探り合いながら行動するようになる。 その結果生じたことについて、上の人間は誰も責任を取らない。

(追記2016/12/24 23:04:18 UTC: もっと言っちゃうと、これ、 カルト内部で集団心理が形成されるのと全く同じプロセスなんである。 トンデモな教祖になぜ人がついてゆくか。 それをまるきり信じ込む人だけが信者になるのではない。 「あの発言は文字通りの意味じゃなくて象徴だから」 という前提を置くと、大抵のトンデモ発言は正当化できてしまう。 頭の回る人ほどそいういうのが得意だ。 各メンバーに、そのカルトに居つづける個人的な理由がわずかでもあれば、 トンデモ発言はそこを離れる理由にはならない。 そして誰かが発言に対する疑問を呈しても、 周囲はあらゆる正当化を使ってそういう疑問を潰しにかかる。 この罠に落ちた集団を内部からの力のみで変革することは極めて難しい。)

これが企業なら、数字で結果が出るから、 どうやったら市場にうけるかを探りながらうまく手綱を調節して、 最終的に損をしなければビジネスとしては成功であると言えるかもしれない。 しばしばトップに極端な人物を置いて 側近が実務をしっかり締めることでうまく回る場合もあるかもしれない。

損をだれかに押し付けて切り抜けることがあっても、 自分が常により大きな力を集めている限り、 損を被って去る人よりも寄ってくるサポーターの方が多くなる。 マイナスが大きくてもそれを上回るプラスがあればビジネスは回る。

けれど、国家の運営はそうはいかない。

「この州は税収に貢献していないから」とリストラすることは出来ないし、 トップダウンの方針が気に入らない奴は出ていけ、と言うこともできない。 結局うまくいかなかったから国を畳みます、というわけにもいかない。

言葉でもって方針を示し、それを国民から承認されることで、信託された力を行使する。 その原則が崩れてしまったのが、何よりもヤバい。

Tag: 生活

2016/12/22

call/ccはいつ使う?

(この記事はLisp Advent Calendar 2016の23日めの記事です)

昔のTVは、取扱説明書に回路図がついていた。 中学校に上がるか上がらないかの頃、多少電子工作をかじって背伸びしていた私は 家のTVの回路図を眺め、 「ここを映像信号が通ってるはずだから、この信号を取り出してカセットテープに録音したり 再生した信号をここに流し込んだらビデオになるんじゃないか」とか無茶なことを 考えて試したことがある。まだ周波数帯域という概念を知らなかったんだな。


さて。第一級継続とそれを取り出す手続きcall/ccは、 Schemeの特徴としてよく挙げられる。 使い始めの頃は、よくわかんないけどなんだかすごそうな機能に見えて憧れたりする。 いくつかcall/ccを使った例を実装してみるうちに、 安全なsetjmp/longjmpみたいなもんにすぎない、と納得できるんだけど、 いざこの機能をどう使えば良いか、となると難しい。

普段のプログラミングで使えそうな場面は、まさにsetjmp/longjmp相当の、 関数呼び出しの深いところから脱出する時くらいのものだろう。

例えばハッシュテーブルのすべてのキーとその値に与えられた手続きを適用する hash-table-for-each (refj:hash-table-for-each) がある時、 「述語predを満たすキーと値を見つけたら捜索を打ちきってreturnする」 なんてのが書きたいとする。 Schemeにはreturnが無い(「WiLiKi:Scheme:なぜSchemeにはreturnが無いのか」)から、 こういう時は継続の出番だ。 (処理系にlet/cc (refj:let/cc)などの簡略化マクロがあれば、 call/ccよりそっちを使った方が見やすいだろう)

(define (hash-table-any table pred)
  (let/cc return
    (hash-table-for-each table  ; tableを順次調べ、predが真を返したらreturn
       (lambda (key val) (let ((r (pred key val)) (if r (return r))))))
    #f))  ; 見つからなかったら#f

しかしこれ以外の応用となるとどうだろう。 良く例外処理だのコルーチンだの非決定性計算だのが挙げられるけれど、 普通のアプリケーションプログラミングをしていてこういった制御構造を「自分で」 書く必要に迫られることは滅多にない。というより、むしろこれらの機能を 処理系が提供しているなら、自分で書くのは避けた方が良い。

例えば例外処理なら、最近のSchemeにはguardがあるはずだ。 自分でcall/ccを使って例外処理を書いてしまうと、 組み込みのguardを使った他のライブラリと整合性が取れなくなる可能性がある。

コルーチンにしても、目的に特化したものなら例えば gauche.generatorモジュール(refj:generate)、あるいはSRFI:121(refj:make-coroutine-generator)等がある。 これらは内部的には継続を使っているんだけれども、 アプリケーション層でそれを気にする必要はない。

プログラミング言語のユーザに、「言語を使ってアプリケーションを書く人」と 「言語仕様を決めたり実装したりする人」という区別があるとしたら、 call/cc は「アプリケーションを書く人」にとっては ほぼ使う必要がない機能と言ってしまってもいいかもしれない。


もちろん例外処理やコルーチンライブラリを「実装する人」はcall/ccを使うんだけれども、 もしこれが「一つの処理系によって仕様が決められるような言語」であれば、 call/ccみたいな面倒くさい機能をわざわざ 仕様にする意味はあまりない。 新たな制御機能のアイディアを思いついたら、処理系のソースを直接いじって実装して パッチを投げればいいからだ。

call/ccは、原理は単純なんだけれども、 現実の実装に課す制約が多い機能でもある。特に関数のcall/returnを主流の言語の実行モデルに 合わせたい場合に色々面倒が多い。既存の言語の多くが、やろうと思えばcall/ccを 提供できるとしても、それをやらずに目的の制御構造を直接実装してしまう理由のひとつは それだろう。実装を複雑にしてまでcall/ccを実装するメリットが見えないというわけだ。

それでもSchemeがあくまで call/cc にこだわるのは、 別にそれが伝統だからとかアカデミックに重要だからとかかっこいいから、ではない。


プログラミング言語は、コンピュータで実行するプログラムを書く言語であると同時に、 プログラムについてのアイディアを人とやりとりするための言語でもある。 アルゴリズムを説明するのに、全て自然言語で説明するのはあまりにまどろっこしく 不正確だ。擬似コードでも良いが、ディテイルまで 詰めたければ明確な定義のある言語で書くのが結局は一番手っ取り早かったりする。

そのアイディアの説明であるコードが、直接実行できて動作を確かめられるなら、なお良い。

call/ccは、新たな制御構造のアイディアを議論する際に、 直接制御の流れをいじれて、かつ比較的明確な定義があるプリミティブ、として活躍するのである。

R6RS以降標準となった例外機構のguardは当初SRFI:34で議論された。 その参照実装を見ると、call-with-current-continuationがネストしていて 慣れないといかにも恐ろしげに見える。 でも慣れるとむしろどのコードがどの動的環境で実行されるかが明確に示されているので、 なまじ曖昧に自然言語で説明されるよりもわかりやすいのである。 (なお、実はGaucheのguardにはknown bugがあって srfi-34と完全に同等になっていない… 効率を落とさずにサポートするのが今の実装では面倒なので先延ばしにしている。)

部分継続(refj:gauche.partcont)みたいなトリッキーな制御構造も、効率を考えなければcall/ccで実装できて、それは意味を考える上でも、実装の際の動作確認の比較対象としても、とても有用だ。

このように、「言語の仕様を考えたり実装したりする人」にとって、call/ccというのは新たな制御構造を試すのになかなかに便利なツールなのである。 (ただし、トップレベルの継続のように仕様が曖昧な部分も無くはない。)


先に、プログラミング言語のユーザに、「言語を使ってアプリケーションを書く人」と 「言語仕様を決めたり実装したりする人」という区別があるとしたら、と書いた。 けれども、そういった区別は必要だろうか。

Lisp系言語は、"Programmable programming language" と呼ばれてきた。 その言語を使ってプログラムを書く、だけではなく、 その言語を使って言語自身をいじるための言語でもあるということだ。

もちろん、言語仕様は誰かが便利に決めてくれればいい、それを使って アプリケーションを作ることに関心がある、というユーザもいていい。 でも、「なんかこのパターン毎回書いてるけど言語組み込みになってたら便利じゃない?」とか 「今はこういう仕様になってるけどコーナーケースはこう動くべきじゃ?」とか 「やっぱり言語にはGOTOが必要だ!」とか 思いついちゃった時に、

  • そのアイディアをコードとして明確に書き下して、
  • 自分で実行して確かめられて、
  • さらに他の人とシェアして別の処理系で試してもらったり新しいアイディアをもらったりする

ってことが出来たら、それはそれで楽しい。そうやって練ったアイディアがいずれSRFIに、そしてRnRSへと反映されてゆくかもしれない。


昔のTVについていた回路図は、ほとんどのユーザにとっては無用の長物だったろう。 けれども町の電気屋さんは持ち込まれた近所の家のTVを直すのに重宝しただろうし、 腕に覚えのあるお兄さんは魔改造するのに使ったかもしれないし、 電子工作少年の心をくすぐるのにも十分だった。 その気になれば、中身に手を突っ込んでいじれる、そのための共通のコトバとして、 call/ccをとらえてみるといいかもしれない。

Tags: Programming, Scheme, call/cc

More entries ...