ユユユユユ

webエンジニアです

Elixir: bitstring を再帰で作るパターン

bitstring を accumulate する手続きには癖がある、という話。

ACGT を2ビットで表すとして、対応表をこうおく。

nucleotide bits
A 00
C 01
G 10
T 11

で、引数として渡される charlist を bitstring に変換する関数 DNA.encode を定義する。先に動くコードを書くとこうなる。

defmodule DNA do
  def encode(dna)
    do_encode(dna, <<>>)
  end

  defp do_encode([], encoded), do: encoded
  defp do_encode([head | tail], encoded) do
    do_encode(tail, <<encoded::bitstring, encode_nucleotide(head)::2>>)
  end

  defp encode_nucleotide(code) do
    case code do
      ?A -> 0b00
      ?C -> 0b01
      ?G -> 0b10
      ?T -> 0b11
    end
  end
end
<<encoded::bitstring, encode_nucleotide(head)::2>>

で bitstring をコンストラクトする、という表現がとにかく難産だった。

まず ::2 を書き忘れると、これは単に Integer の表現として評価されてしまうので、エラーこそ出ないが padding zero が落ちてしまう。

encoded が bitstring なのは自明だから、と思って

<<encoded, encode_nucleotide(head)::2>>

とすると非自明な ArgumentError が出る。これはなにも教えてくれないので、デバッグのしようもない。

迷走して、 <>/2 を使おうとしても、ここで扱おうとしている binary は 2-bit であるから、「8-bit にしろ!」と怒られてしまう。

苦心惨憺して、動くコードを書けはしたが、正直言って数撃ちゃ当たる戦法の試行錯誤がたまたまヒットしたというだけであって、ちゃんとドキュメントから演繹的にたどりつくことができたわけではない。

かなり苦しい時間を費やした。悪態をつかなかったとは言わないが、「でも誰に向けて?」というやり場のなさを、こうして吐き出すことで弔うことができればと思う。

新しいルールを学ぶというのは本質的にこういう経験の繰り返しであったな、ということを思いつつ、さじを投げなかった自分を褒めたい気持ちもある。

少なくとも、ここでひとつのパターンを手痛い思いをしながら見つけたので、これは繰り返さないように戒めとしておく。

SICP が届いた

SICP が届いた。

f:id:jnsato:20220117232402j:plain

amazon のレビューを見ていても、みんなが口を揃えて「この本は異常なほど難しい」「しかし読む価値は確かにあった」と、他に類をみない推薦文が並んでいる。

teachyourselfcs.com で言及されていた、 UC Berkeley CS 61A という講義のウェブキャストアーカイブ1も並行して見ていってみる。いちおう再帰関数の予習は The Little Lisper で済んでいる2ので、そうやすやすとは置いていかれないぞという気概でいる。

Robert Martin が SICP を語るビデオ3なども見つけた。10年ばかり前にこの本を読んで、いまではイミュータビリティの信奉者だと言っている。 Closure をメインで書いているのだそうだ。

確実に世界を変えてくれる本とわかっていて臨むのはスリリングである。 Harvey 教授も言っているが、枕の代わりにして眠るくらい、じっくりと読み解きたい。実際ペーパーバック版で 600 ページあり、小さな枕のようだ。

仕事に責任を持つことよりも、知性を磨いてコンピューティングを楽しむこと。そういうことが扉に書いてあって、そうだよなあと思っている。

The Little Schemer を読了

The Little Schemer を読了した。正月休みに読み始めていた。

ひとくちに再帰といっても、よくわかっていないところが多い。うまく制御できずに無限ループを引き込んでしまうのが怖い。そういう畏怖に似た感情をもつ人は少なくないのではないか。かくいう僕自身がそうであった。

以前に Scheme のチュートリアルに取り組んだときには、末尾再帰という概念を覚えた。単純なループを再帰で表現できるというアイデアになるほどと納得したいっぽうで、いきおい特殊なケースにしか適用できない、つまり単純でないループでは不利になるような印象は残っており、難しいなという印象は変わらず残っていた。

関数型言語というものについて、どうにもお客様のような立場で入門をしては離れて、を繰り返してきた。言い換えると、あれこれ手探りで取り組んでみるが、体得できたという感覚を持つことはできていなかったわけだ。そこにきて本書が、いよいよ関数プログラミングの本質的なコツを伝授してくれたという実感がある。

本書の表紙裏には、十戒になぞらえた10個の原則が掲げられていて、これらをひとつずつ咀嚼するように教育してくれる。原則ありきで実践を促されるわけでなく、実践ありきの野暮な原則になるわけでもなく、原則と実践が一体となって提示されるように本文が運ばれている。対話を模倣したスタイルで進行する本文も親身である。総じて、簡単でない内容が平易に、実例豊富に、ユーモアを添えて、コンパクトにまとめられていて、古典たる由縁を思い知らされた。名著である。

ごく簡単な事例から入って、自然再帰という方法論から再帰関数の定義をごくシンプルに定式化してみせる。それだけで十分値打ちがあるはずが、さらに深く(とおもうのは読み手の力量不足にすぎないのかもしれないが)潜りこんで、コラッツ予想、アッカーマン関数をジャブにして、ゲーデル不完全性定理が実例とともに示される。そうして計算不可能性というものを思い知った上で、最後の章ではなんと Lisp インタプリタLisp で実装することになる。思いもよらない難度の課題に尻込みもしつつ、親身なテキストのおかげで、(実態としてはコードを写経したにすぎないとはいえ)インタプリタが出来上がってしまった。恐るべきことであった。

続編として、 The Seasoned Schemer という教科書がある。独立した応用編というよりも、最初から二巻本として意図されている様子であることが、あとがきの代わりに「インターミッション」という見開きが用意されていることからもわかる。これも素敵な遊び心である。

その「インターミッション」も破格のものである。いわく、すぐに続編に進まずに、ぜひしばらく時間をおいて、リラックスし、またやりたくなったときに続きを求めてほしいとのことである。この商売っ気のなさよ! 帝王的なスタンスにいっそう思い入れを深めざるをえない。

The Seasoned Schemer に進むより先に、『不思議の国のアリス』を読むように勧められている。これもまた、アカデミズムの遊び心を感じる。社会の荒波に揉まれて失念していたが、大学というのはこのようにして、遊びと研究が渾然一体となった、幸せな環境であったのだなと思い出す。難しいはずのことを、このようにのびのびと、ユーモラスに伝えてくれる先生というのは、僕にとって幸いなものであるし、未来の社会にとっても必要不可欠なものであるのだろうな、と思いを馳せた。

期末試験おしまい

放送大学の科目履修生をやっており、最初の半期の期末試験があった。それをいましがた郵便で提出してきた。10月からの学期中、平日夜と週末をほとんどすべて費やすようなやり方で走ってきたので、これにてひと段落という区切りに安心もひとしおだ。

履修していたのはこの5科目。

  • 1160028:初歩からの数学(’18)
  • 1559257:西洋音楽史(’21)
  • 1760041:入門微分積分(’16)
  • 1760106:初歩からの化学(’18)
  • 1760114:入門線型代数(’19)

振り返ってみると、これらの分野をやってみたい! と思い立ったのが昨年のゴールデンウィークのことであったから、いうなれば 2021 年の大きな目標のひとつを達成できたということで、満足している。そのあたりの経緯はこのあたりで書いていた。

微積線型代数にとにかく一生懸命になっていた。なにせ高校までのカリキュラムを復習しつつ大学の講義を受けていたわけで、あれこれ前提レベルの議論に脱線しながら予習をする必要があって、効率はそれほどよくなかった。しかし現役生にも負けないくらいにやり込んだ自負はあるし、期待していた学習成果はたしかに挙げられたようにおもう。

大学からあらかじめ送られてきていた演習問題に年末年始に取り組んでおり、ちょっと難易度が高めかもしれないと怯えていた。試験前の一週間に、試験対策に過去問を解いてみると、教科書と演習問題を理解できていれば難なく答えられるように問題設定されていることがわかって、リラックスして試験に臨めた。マークミスをしていなければ、単位取得は問題ないだろう。10年ぶりにマークシートを塗り潰した。

45分の講義の予習のために、土曜日を朝から晩まで費やすようなこともあった。残りの科目の履修を日曜日にやって、それで週末が終わってしまうようなスケジュールだった。と書くといかにも苦行をアピールしているようだが、不思議と辛さはなかった。計算がうまくいかずにフラストレーションを溜めたことこそあれ、最後には気持ちよく答えが導けるから、その過程で呻吟するのは苦痛でなかった。そういう特質を自分のなかに見出せたことも自信になった。

今日から2ヶ月半は、学期間の充電期間になる。春休みだ。やりたいことはたくさんある。 Elixir のチュートリアルが途中までになっていたし、その前に The Little Schemer も読破したい。 SICP も読みたい。線型代数の副読本として、小寺先生の『明快演習 線形代数』がいいときくので、これもやりたい。そんな春休みを過ごしたら、今期の続きの科目を取ろうとおもう。解析と線形代数の二科目は必須として、他にどんな面白そうな科目があるのか、履修科目リストを眺めるのも幸せな時間である。

2022年は Starfield をプレイする以外に目標なし

https://bethesda.net/en/game/starfield

windows マシンが必要になるのであれば、それを準備するのが秋までの小目標になる。

有給休暇をできるだけためておいて、一週間の休暇をあててじっくり遊んでやろう、と目論んでいる。

最新ビデオゲームが次々にやってきて、それを次々に見送ることに慣れてきてしまっている。しかしベセスダに育てられたキッズのひとりとして、これだけは見逃したくない。

新作ゲームをすぐに遊ぶという体験をしたのはポケモンルビーあたりが最後のはずだから、そうやってゲームをする楽しみをここでもう一度味わいたい。それに値するタイトルはこれ以外にない。

The Little Schemer を読み始めた

Cがコンピュータがどう動作するかのモデル化に最も適した言語とすると、Lispは計算というものがどう振る舞うかをモデル化するのに最も適した言語だ。ほんとのことを言って、Lispについて多くのことを知る必要はない。一番シンプルでクリーンなSchemeを使い続けることだ。他のLisp方言はライブラリやらツールやらを備え、C++Javaが持つような大きく複雑なプログラミング環境へと成長している。そういう部分については知っている必要はない。ただSchemeでプログラムを書ける必要がある。The Little Schemer と The Seasoned Schemerの練習問題を自力ですべて解ければ十分だと思う。たぶん。1

というエッセイを読んだのがずっと心に残っていて、以来ほしいものリストのトップに入れてあった The Little Schemer2 を年末に手に入れて、読み始めている。

昨年のゴールデンウィークに Yet Another Scheme Tutorial をやった3。そのときは深入りする余裕を持っていなかったのでひとまず撤退したと書いている。

ウィザード本を目標として持っていたが、放送大学の期末試験を控えて新しいカリキュラムに手をのばすのは気が引けて、もう少し軽い参考書としてこちらをやってみる。

cons car cdr のどれがどれだったかを忘れてしまっているあたり、我ながら情けなさも感じかけたが、思い出してみればある程度スラスラと読める。主要な概念がインストールされていることの現れなのであれば嬉しい。

実装は昨年同様に mit-scheme4 を利用している。

放送大学「入門微分積分」全15回を完走した

高校レベルの微分積分までしか学んでおらず、しかもそれさえほとんどうろ覚えという状態から、初級の定理をおおむね理解し、計算することができるところまで3ヶ月でやってこれた。

毎週末に一課ずつコツコツと進めてきた。そのときそのときで、理解できるまで証明を咀嚼するように努めてきた。おもしろいことに、いくら読んでもよくわからない証明が、ノートに書き写すととたんに理解できたりする。そうした甲斐もあって、なにか難しい定理が現れてきても、そこまで学んできた内容をうまく使ってきちんと論理を追いかけられるということに成長を感じた。

計算結果が合うと嬉しい。合わないと悔しい。悔しいので、合うまで粘る。そういうやり方で向き合ってきた。効率よく学んだという気はしないが、だからこそ確かな力が身についているはずという自信が持てる。

いっぽうで、証明の再現までするとなるとかなり苦しさがあるのは否めない。とはいえ最終講義での石崎先生のアドバイスによると、まずは計算演習ができることが先で、その上でさらに学習を深めるために証明の再現をおこなうべしとのことである。

もっと学びたい熱意はある。次の講義をとるのも楽しみだし、翻ってここまでの内容を復習したり、あるいは参考文献に挙げられていた初等の参考書にも手を伸ばしてみたい。

しかし何はさておき、まずは演習問題をクリアして期末試験の準備を万全のものとしたい。科目等履修生であるので、単位を取得することが必ずしも重要ではないのだが、最後まで取り組むことで画竜点睛としたい。