あざらしとペンギンの問題

主に漫画、数値計算、幾何計算、TCS、一鰭旅、水族館、鰭脚類のことを書きます。

英語ができない

昔から英語に対する苦手意識がありました。単語を覚えるのが退屈で仕方がなかったこと、そもそも日本語でさえ上手くコミュニケーションが取れないのに、況してや英語でだなんて冗談ではないと思っていました。私が理系に進んだのは、単純に理科が好きだったからというのが大きいですが、もうひとつの理由として、現場の技術者になれば英語を使わなくても十分やっていけるだろうというネガティブな考えがありました。残念ながらその見通しは甘すぎたというのが過去を振り返って思うところです。

出身高校(水族館)での私の英語の成績は、下の中くらいだったと記憶しています。化学が好きで得意だったというのは前に言ったかもしれませんが、英語は散々な思い出しかありません。模試の理系総合には英語が含まれていたので、それが明らかに足を引っ張っていました。例の全統模試の偏差値は 72-74 くらいで上位1%に入るかどうか程度でしたが、英語がまともにできればもっと上に行けたと思います。しかしながら、たま多摩センター試験では9割取れたので、あれはまぁ当てにならないなと思いました。

私の出身校は帰国子女が多かったこともあり、英検2級で普通くらいの印象で、準1級もそれなりの数いて、1級も少数ながらいるという環境でした。英語の授業も(私にとってては)高度で、予習をして望まなければフルボッコにされるといった雰囲気で、試験に出される長文は冗談かと思うほどの長文でした。東京/京都大学をターゲットにしている授業だったので、それくらい求められるのは当然といえば当然でしたが、とにかく英語には悪い思い出しかありません。

とはいえ大学に入ってからはそれなりにやっていけました。というのも、理系専門英語のリーディングは意外なほど簡単なのです。専門用語は確かに聞き慣れない難しい単語が多いのですが、それは嫌でも覚えることになります。それに対して文章はストレートな表現で書かれているので、読むのに苦労することは少ないです。

筆者が英語圏出身でない場合が多いことはかなり関係していると思います。英米の筆者の文章は難度が上がるような気がします。同様に、英語で行われる講義や発表においては、話者が英語ネイティブかどうかはかなり大きな違いに聞こえます。ネイティブの方が表現が多彩な上にスピードが速いため、数段難しいのです。いわゆるイディオムもネイティブの人は普通に使いますが、非ネイティブの人が使っているのはそれほど聞きません。A couple of … のような中学レベルのイディオムともなれば、ネイティブは当たり前のように使ってきます。こんなところでイディオムの重要性を知るとは随分と遅い話ですね。

正直な感想を言わせてもらえば、日本の研究者には英語嫌いの人が多いと思います。当然ながら論文は英語で書かれていますし、自分で書く場合も英語で書くのが当たり前になります。英語で話すイベントは国際発表のみならず、外国人研究員や留学生と話す場合など日常的に発生します。

私がどれだけ英語が苦手でも、論文を読むのはさすがに慣れました。明らかに英文よりも内容の方が難しいので、英語で詰まっている場合ではないのです。前述の通り専門の英語は簡単なので、論文を読むことの難しさでは内容の難しさが大半を占めます。

しかし、会話に対する苦手意識は今でも抜けません。先に上げた国際発表、研究員、留学生らとの議論といったイベントは当然私にも発生しました。理系でやっていく以上英語を避けては通れないということに、大学院まで行ってようやく気づくとは、遅いなどというものではありませんね。タイムマシンがあれば過去の私に言ってやりたいところです。(私は天邪鬼なので他鰭の指示など聞かない可能性は高いですが。)指導教員からも、D進するにしても就職するにしても、うちの大学を出て英語と無縁でいることはできないと言われました。まぁその後アレしたのですが。

以前にも言ったと思いますが、私は運良く UC Berkeley(計算機科学においては東の MIT と並ぶ名門)に滞在することがありました。当然周りは英語を話す人しかいないわけです。(アジア系やヒスパニック系が多い土地柄、中国語やスペイン語なども当たり前のように話されていましたが。)しかし、そこで思ったのは、外国にいるとむしろ英語が下手になるのではないか?ということでした。一時的にモチベーションは上がるものの、惰性になっていくとそこで止まってしまい、最低限の英語でサバイバルしていくようになってしまうのです。

このままではいけないと思ったのは、日本の国内事情を見てからです。私は国内の様々な地域を列車で旅しましたが、観光地はどこに行っても外国人の方が多いのではないかと思いました。田舎では移動は自家用車が当たり前なので、鉄道を使うのは学生か観光客が大半となります。そうすると、列車にはほとんど外国人しかいないという場面に出くわすことが度々ありました。観光地の人も外国人を相手にすることが日常的となっていて、なんとか通じる言語として英語を使うというのを何度も見てきました。私も外国人に間違えられることが何度かありました。

私は旅に出たり土地のことを調べたりして、おそらく人並みよりは日本のことを知っていると思います。良い部分悪い部分含めて。外国人から日本のことを訊かれることはそれなりにありました。しかし、私は英語が得意ではないので、十分に伝えるように話すことが難しかったです。日本語でも難しいのだから況してや、といったところです。日本人は多くが外国に対して内向きに思われますが、変に日本を持ち上げる人、逆に変に外国かぶれした人も少なくないという印象を私は持っています。いずれにしても日本そのものに対しては無頓着に思われます。盲目的に日本を上げるのも外国を上げるのも馬鹿らしいと思います。

日本はもはや先進国ではないと思いますが、後進国というのも間違いで、『後退国』であると私は思います。それ程度にはこの国に未来があるとは思いません。私は漫画やアニメなどのいわゆるオタクコンテンツというものが好きです。しかし、日本がその先端にいられる時間はもうそれほど長くはないと思ってもいます。日本のある分野に対する優位性は、ほとんどが遠からず他国に奪われるか、あるいはそのもの自体が消滅するかのいずれかに落ちると現実的に考えています。

私は日本という国に対してはさほど思い入れはありません。しかし、日本がこれまでに作り出してきた様々なものに、それなりに重い思い入れがあったりします。日本で内向きになることも日本をないがしろにすることも、それらを維持、発展させることに対して何の貢献もしないのは確かです。私は私自身に関してそれらに属することを好ましいとは思いません。

ここで必要になるのは、やはりまずは英語であると思います。それは私が避けようとしてきたものです。現在、私は一応何かを発信する立場として、英語を避けることは発信しないこととほとんど同義であると思っています。そして、私が伝えたいことを表現するためには、サバイバル英語では全く足りないとも感じています。そのためには英語を深く使いこなすことが必要であると考えます。ニュアンスに無知ではダメで、目的に応じて硬軟を使い分けることも重要です。ライトノベルがいきなり明治の小説になっては滑稽でしょう?

というわけで、しばらくは英語を頑張ってみようと思います。まず伝えたいことは「現在の日本には忍者も侍もいない。ただ人身売買はある」ということです。

では。

広告

私のプロフィールページと、かねてより作る作ると言っていた『天之御船新聞』、の前に土日に実施している『あんハピ♪』ワンドロのギャラリーを作りました。それと新聞の正式名称を Argonaut Herald に決めました。『天翔る船の使者』という意味で、『天之御船』と英語圏の新聞によく使われる Herald という名詞を合わせました。上であれだけ言っておいて英語版の記事を書かないわけにはいかないですね。

https://azapen6.github.io/
anhpms.org

城の崎にて、あざらしを観てきた

Twitter の陰謀によって突如としてキビヤックにされたくろは先生が掘り起こされて新たな生を始められたということで、もうこれはイースターと言っても過言ではないですね!あざらしの卵を用意しなければ!

とはいえ、聖遺物であった『アザラシック・ワールド』のツイートが失われてしまったことは大変悲しむべきことです。我々はこの事件を深く心に刻み、いざとなれば訴訟を起こす構えを示さなければなりません。本件において仮に Twitter 社が凍結されたアカウントをすべて復活させて事件をなかったことにしようとしても、既に大量の証拠が残されてしまっている現状では、それも不可能でしょう。ただ、こちらとしても実際に訴訟に持ち込むことは現実性がないでしょう。利用規約において、Twitter は利用者に対して理由の如何を問わず無制限にアカウントを停止する権限を有するとされています。現行の規約ではアカウントの停止に対する異議を唱えることができるとされていますが、Twitter がそれに応じるかどうかについては何も定められていません。というか読んでみると整合性がアレでこの会社マジでダメなんじゃないかと

https://twitter.com/en/tos

いつもの長いアバンはこれまでとして、タイトルの通り、城崎温泉に行ってきました。私の誕生日が9月1日だったので、その記念と18きっぷの使用を兼ねて。残念なことに出遅れて特急を使うことになりましたが……私にはお金がないので痛い出費でした。到着が21時と遅くなったので、その日は旅館に泊まっただけで、観光したのは翌日です。

さて、城崎温泉といえば、志賀直哉の『城の崎にて』が有名です。1913年8月、東京を訪れた志賀は、山手線にはねられて重傷を負いました。命は助かったものの、しばらくの療養のために彼が訪れたのが城崎温泉です。生々しく死を突きつけられた体験は、彼の頭に深く刻まれたのでしょう。1917年、志賀は同人誌『白樺』に短編『城の崎にて』を発表されました。それは彼の代表作のひとつとなり、現在までその名をとどめています。

文学史上に現れる鉄道人身事故では、レフ・トルストイの『アンナ・カレーニナ』もよく知られます。本作の主人公であるアンナは、列車に身を投げて自殺しました。先の志賀直哉は本作を高く評価しており、近代小説の教科書とまで言ったようです。それだけ志賀にも影響を与えたということでしょう。彼が列車にはねられたのはもちろん偶然ですが、それがもとで傑作が生まれたことには、不思議な縁を感じるところがあります。

さて、私の話に戻りますが、城崎温泉へ行こうと思ったことの決め手は、『帰宅部活動記録』(作:くろは)の文学回(アニメでは5話)に登場する次のあざらしでした。

f:id:azapen6:20170916055331j:plain

つまりは『城の崎にて』からの縁で私は城崎温泉を訪れたのです!もちろん作品はちゃんと読んでいますよ。現地に持っていって読めればよかったのですが、出発からドタバタして結局なりませんでした。

城崎温泉の旅館に泊まると、外湯巡りのフリーパスがもらえます。これは外湯の受付でバーコードをかざせば無料で入浴できるというものです。泉質は駅前の飲泉所で飲んでみればわかる通り食塩泉です。城崎では浴衣に下駄が正装というように、旅館で借りた浴衣と下駄の姿で外を出歩くことができます。下駄の音を鳴らして歩くなんて風情があって良いなぁ、と思ったのは最初のうちで、鼻緒を挟んでいる指の間が痛くなったのを我慢して歩きました。旅館に戻った頃には指の間から血が滲んでいて、優雅を気取るのも楽ではないな、と思いました。

旅館を出た後は温泉街を観光した後、近くにある水族館『城崎マリンワールド』に行きました。もちろんここを訪れることも旅の目標でした。それまで持っているだけだった障害者手帳がここで初めて役に立ちました。水族館の情報はウェブサイトを観てください。

marineworld.hiyoriyama.co.jp

もちろん私が観に行きたかったのはあざらしとペンギンがいる外の水槽なわけで。あざらしの他にもアシカ、トド、セイウチが出揃っていて、アシカ・イルカショーもアシカの方に重きが置かれ、セイウチがボスとして出てくるといったように、かなり鰭脚度の高い水族館でした。アジを釣って天ぷらにするという他にはないアトラクションもありました。「美味しい天ぷらを、釣りましょう」という見も蓋もない文句、好きです。とはいえ時間と金の関係でパスして、水族館を後にしました。

今回は旅の話を書きましたが、実際のところ私にバリバリ旅をしたりイベントに出たりする余裕などはありません。保険・障害関係の手続きは1回あたり2-3ヶ月待たされるのが普通なので、尿と吐瀉物にまみれた東京という土地から名実ともに去ることは、近いうちには難しいでしょう。

最後に行った大きなイベントは、7月にあった『うらら迷路帖』アニメのイベントでした。一言で言えば、最高、でした。『うらら迷路帖』は原作から好きになった作品ですが、アニメ7、8占は合わせて5回泣けるほど濃い話数でした。どうでもいい話ですが、私が前回の『よんこま小町』に出すつもりで作っていた同人誌『迷路町通信・第壹號』のデザインは、上で言及した文学同人誌『白樺』を参考にして考えました。変なところで話はつながるものですね。

うららイベントでは、それまでとは一転して、先輩としてちゃんと進行をされていた諏訪彩花さんが登壇される『SSちゃんねる』のイベントは、昨年は4公演全通しましたが、今年は行けそうにありません。

昨年といえば春の『あどりぶ』のイベントにも当選して行きました。最前列でゆっこさんを直前に拝める神席でしたが、むしろスカートの中が見えそうで鰭が鰭でなかったのは良い?思い出です。

1日早いですが巽悠衣子さん、お誕生日おめでとうございます。『下向き』は毎回神回です。これが 324 円払えば実質無料だなんて信じられません。『けいおん!』から『kiss×sis』を知って、この強そうな名前の美人は誰だ?けいおん!にも出ていたのか、いうところから随分と年月が経ちました。ずっと応援していたとはとても言えませんが、これからも応援しています。金の続く限り。

後は辞世の句でも詠めば締められるでしょうか。残念ながら私はいきなり何も考えることなく死ぬのが理想なので、そういうことはしません。

では、本当に最近の話をしましょう。最近は絵もあまり描けていなくて、1日の記憶があまりありません。

まず結構大きかったのは、sbt がメジャーアップデートされ、遂に Version 1.0 がリリースされたことがあります。『天之御船学園放送部♪』@anhpmsbot は現時点では sbt 上で動いているのですが、それまで長期間走らせておくと再起動時に変なエラーで落ちていたのが無くなって、安定した運用ができるようになりました。これで Scala での開発が捗り、30億のデバイスで走るようになればいいと思います。

今のところの主力開発言語はこの通り Scala ですが、同時に OCaml も主力に加えようとしています。理由は、速度面で有利であること、また、F# の中核をなす言語であることから、ウィンドーズで何かを作らなければならなくなったときにも対応しやすいことなどがあります。まぁ、プログラム言語はあくまで道具ですので、覚えた数など問題ではなく、しかし使える武器が多いことに越したことはないといったところです。

『天之御船学園新聞部♪』anhpms.org はまだ稼働していません。ドメインを取ってからもう随分経つのに実に勿体無いですね。ドメインは namecheap というレジストラで取っています。anhpms.orgWHOIS protection を含めて1300円/年くらいです。何はともあれ早くページを作らないのは馬鹿です。

Domain Names - Cheap Domain Names | Namecheap.Com

体の方では、少し前に『クエチアピン』なる薬が出ました。先発薬が『セロクエル』の名前で通っている有名な薬です。この薬を飲んでからでしょうか、妙に甘いものを欲するようになり、一方で塩気のあるものをあまり欲しなくなりました。普段の食欲が落ちた代わりに、甘いものが無性に食べたくなります。この薬は血糖値を上昇させるため。使用には注意が必要ということです。

『ららマジ』なるゲームをリリース直後から続けてやっているのですが、現時点でやれることをほとんどやり尽くしてしまいましたので、基本的にイベントドリブンです。イベントシナリオでは器学部員達の掛け合いが増えてより楽しくなりました。しかし、今望んでいるのは本編ストーリーの追加と絆レベルの上限解放です。第7幕『マランドリーノ』の完璧なストーリーを観てしまうと、期待しすぎてしまうところはあります。あとは私のこととして、『ららマジ』の絵も描きたいのですけどね。一応フレンドIDを書いておきます。

名前:とっかりーん
フレンドID:RvZA29mz3f

色々なことを詰め込んでまとまりのない話になってしまいましたが、今回はこれで締めることにします。では。

azapen6

Lazy Days

くろは先生が和製キビヤックになられたことについて、謹んでお悔やみ申し上げます。

どうも、最近絵が描けていない azapen6 です。今回の本題は『遅延をスケジュールする』話です。

まずこの題目からして意味が解らないでしょう。遅延とは設定されたスケジュールから遅れることを言うので、まず言葉として矛盾しています。

一体何の話かというと、Scala における値の遅延評価をスケジュールとして設定してやるという話です。

動機

そもそもの動機は Twitter で『天之御船学園放送部♪』@anhpms として運営している bot を書くにあたって、過去のある時点に設定されたスケジュールを実行して得た結果を後から参照したいということでした。例えば、次のようなものです。

  1. 15:00 にはなこが「待って〜、猫ちゃ〜ん!」と言って走り出す。
  2. 15:30 にヒバリがはなこを見つけて「何、してるの!?」と声をかける。

はなこに何があったかはこの際置いておきます。これを実際にプログラムとして書くためには、次のような手順が必要になるでしょう。

  1. 次の手続きを 15:00 に行うように設定する:「待って〜、猫ちゃ〜ん!」とツイートする。結果としてそのツイートを表すオブジェクト status1 を受け取る。
  2. 次の手続きを 15:30 に行うように設定する:status1 に対するリプライとして「何、してるの!?」とツイートする。このとき、1のツイートは必ず存在していなければならない。
  3. 15:00 になり、1の手続きが実行される。
  4. 15:30 になり、2の手続きが実行される。

ここで重要なのは、2の手続きを実行するに当たって、1の結果が必要になるということです。リプライの対象とするツイートが必要なのです。

とりあえずのコード例

このようなプログラムを、例えば Groovy を用いて書くのは簡単です。以下、schedule(hh, mm) { proc } の記法によって、hh:mm にクロージャとして定義された手続き proc を実行するように設定することを表します。

Groovy

Groovy では次のように書くと望み通りのことができます。以下、ツイートは tweet(text)、リプライは reply(replyTo, text) というメソッドで行うこととします。ツイートに失敗した場合、あるいは replyTonull の場合は例外を投げるとします。

実のところはどちらも同じく Twitter APIstatuses/update を用いるので、リプライの相手がない場合は普通にツイートされてしまいます。reply メソッドはそのような場合を排除するものと考えてください。

def status1 = null

// 1の手続き
schedule(15, 0) {
    status1 = hanako.tweet("待って〜、猫ちゃ〜ん!")
}

// 2の手続き
schedule(15, 30) {
    status2 = hibari.reply(status1, "何、してるの!?") // ここで status1 が必要
}

ここで注意すべきは、ふたつのクロージャが変数のバインディングを共有しているということです。まず、スケジュールが設定された時点では、status1 には null が入っています。それぞれのクロージャこの status1 に対して読み書きを行うことができます。つまり、最初のクロージャで代入する変数 status1 は、その括弧の中だけに束縛された変数ではありません。よって、そこで代入を受けた status1 の値は2番目のクロージャで使うことができます。

1の手続きで Twitter への投稿が失敗した場合は例外が投げられるとします。ここでは何の例外処理もしていないので、そのままプログラムが落ちて2の手続きは実行されないでしょう。

もし何かの間違いで手続きの実行順序が逆転してしまった場合、status1 = null のまま2の手続きが実行されてしまい、やはり例外が発生して落ちます。

これらのようなエラーが発生しなければ、上のプログラムはスケジュールに従って正しく実行されるはずです。

Scala

さて、ここからが本番です。実を言うと、Scala でも大体は上と同じようにコードを書くことができます。しかし、そうしたくない理由があります。それは、『変数への代入』です。

変数への代入は関数型プログラミングにおいては原則としてすべきないと見なされています。なぜなら、代入の副作用によって関数の評価値が変わってしまう場合があるためです。関数型プログラミングでは、関数の同じ引数に対する評価値は常に同じであるべきです(参照透過性)。副作用は可能な限り避けることが望ましいので、上のような書き方は宜しくないというわけです。

変数への値の代入を最初の一度だけ行うことにすれば、そのような副作用が起こることはありません。この場合、変数はもはや変数ではなく、決まった値に対する名前でしかありません。変数への代入は名前への関連付け、アサインメントというものになります。

さて、Scala で値を宣言するキーワードは val でした。値の実質的な代入は前の groovy のコードでも一度しか行われていないので、次のように書けると思われるかもしれません。しかし実際は失敗します。なぜなら、Scala では val にしろ var にしろ宣言時に値のアサインメントを行う必要があるからです。

val status1: Status // エラー

// 1の手続き
schedule(15, 0) {
    status1 = hanako.tweet("待って〜、猫ちゃ〜ん!")
}

// 2の手続き
schedule(15, 30) {
    val status2 = hibari.reply(status1, "何、してるの!?") // ここで status1 が必要
}

もし Groovy のコードと同じように書きたいならば、1行目を var status1 : Status = null と書けばよいでしょう。しかし、これでは実質的に値が変わらないのに変数を使うことになって、Scala 的にはあまりいい気がしません。

括弧の中の status1val をつけるのもダメです。スコープが括弧の中に限定されてしまい、必要となる場所から見えないということになります。

さて、どうしたものか。

遅延評価

以上のことをサクッと解決するのが値の遅延評価です。遅延評価というのは、その値が実際に使われるときになって初めて式を評価するということです。Scala では、遅延評価する値を lazy val で宣言します。怠惰ですね。

理解するには実際に見た方が早いと思うので、簡単なコード例を示します。まず、lazy をつけない場合:

def f(x: Int) = { println("here"); x }
val a = f(1)
println("hello")
println(a)
println("bye")

これを実行すると、次のように出力されるはずです。

here
hello
1
bye

この場合では、val a = f(1) の時点で右辺が評価されるので、here は hello の前に来ます。これを遅延評価に対して先行評価と言います。

一方、lazy をつけた場合:

def f(x: Int) = { println("here"); x }
lazy val a = f(1)
println("hello")
println(a)
println("bye")

これを実行すると、次のように出力されるはずです。

hello
here
1
bye

これは、lazy val a = f(1) の時点では右辺が評価されず、後に println(a)a が要求されたときに初めて右辺が評価されて実際のアサインメントが行われます。だから here は hello の後に来るのです。

遅延評価というのはおよそこのようなものです。遅延評価という用語は、特定の言語が備える特定の機能を指すものではなく、プログラムの実行順序を決めるスキームの一種を指すものです。他にも様々な形で遅延評価を提供するものが数々のプログラム言語にあります。

遅延をスケジュールする

武器は手にしたので、あとは上の Scala のプログラムをサクッと通るようにしてやりましょう。

// 1の手続き
lazy val status1 = hanako.tweet("待って〜、猫ちゃ〜ん!")

schedule(15, 0) {
    status1
}

// 2の手続き
lazy val status2 = hibari.reply(status1, "何、してるの!?")

schedule(15, 30) {
    status2
}

はい。lazy val の評価自体が手続きに含まれるため、コメントの位置を移動させました。見た目上はスケジュールの設定のところで関数を呼んでいるような感じです。

Groovy の場合と同様に、1の手続きが実際に行われる status1 の右辺の評価で Twitter への投稿が失敗した場合は例外が投げられます。当然、そのままプログラムが落ちて2の手続きは実行されないでしょう。

しかし、もし何かの間違いで手続きの実行順序が逆転してしまった場合は Groovy の場合とは違ったことが起こります。status2 が要求されたとき、その中で status1 を要求しているので、その時点で2つのツイートが正しい順序で投稿されるのです。当然ながらスケジュールは狂いますが。

まとめ

今回は、Twitterbot でスケジュールを実行するとき、既に実行が済んでいる手続きの結果が欲しいという議題について、値の遅延評価を宣言する lazy val を使って『遅延をスケジュールする』ことによる解決方法を示しました。

サンプルコードを以下に置きます。Main.scalaprogram 関数に今回書いた内容の例を記述しています。CONSUMER_KEY などは自分で取得したものを設定してください。

GitHub - azapen6/TwitterSchedulerExample: An example code of Twitter scheduler in Scala with akka, using scalaj and json4s.

はてさて、今回の題名は一体何のことやら。