関数型言語の楽しさを知ろう!Racket超入門ガイド
A Friendly Introduction to Racket
A Friendly Introduction to Racket
Racketは、Lispファミリーに属する非常に強力で柔軟なプログラミング言語です。単なる言語学習の枠を超え、独自の言語を作成するためのプラットフォームとしても優れています。教育から研究、そして実用的なツール開発まで幅広く使えるRacketの世界へ飛び込んでみませんか?このガイドでは、Racketの基本概念と、なぜ今多くのエンジニアがこの言語に夢中になっているのかをわかりやすく解説します。
Racketの話題が出るたびに、試せそうな面白いアプリがないか探すんだけど、見つかるのはライブラリや開発ツールばっかりなんだよね: https://awesome-racket.com/ (https://awesome-racket.com/)
『アメイジング・デジタル・サーカス』(第8話「hjsakldfhl」)で、キンガーがケインをリセットしようとターミナルを開くシーンを見ると、ケイン(1996年に作られたクリエイティブAI)がLispでプログラミングされていることがわかる。ファイル名もずばり Caine-core.lisp だ。
いい演出だね。第9話でケインが復活した理由も説明がつくよ。Lispの継続(continuations)を使えば、スマートにエラー復旧ができるからね。
ホットリロードができること以外で、Schemeの魅力がさっぱりわからないんだが…
Racketのファンではあるけど、これは「フレンドリーな入門」とは言えないな。ただのスピードランだ。
「フレンドリーな」入門と銘打つなら、ラムダが何かを知っている前提で話を進めないでほしい。
それと、「フレンドリーな」入門なら、そもそも構文規則なんて一切出てこないはずだ。
言語としては面白いんだけど、悲しいかな、実際に現場で使っている人はいないよね。デプロイの手間がネックなのかな?ネイティブで単独の実行ファイルを生成できれば、普及率は上がると思うんだけど。
特殊な構文は一切なし。
(list '(1. . #\#)
-5/6+7.s-8i
`(1 ,@2)
1@1 ;むむ、アンクォートスプライシングのカンマがない ;-)
10# ;びっくりした?
(list #i+1 +1i 1+i) ;これって複雑なの、それとも複素数?
#e-1e10i ;ゆかいな牧場?
"(* 9 10)" #())
細かい揚げ足取りで悪いけど、Janetについてはここを見て
https://news.ycombinator.com/item?id=26496339 (https://news.ycombinator.com/item?id=26496339)
ちなみに、Racket関連のブログや記事に興味があるなら、ここがおすすめだよ。
俺が1980年にCMUで最初に触れた言語はPascalだった…そのすぐ後にCS/AIの授業でLISP、EE(電気工学)の授業でCをやるようになったんだ。当時はGLSが関わっていたMIT版のMacLispの大ファンだったよ(ソースコードの至る所に彼のコメントがあったからね)。もちろんGLSはその後Schemeに移って、クロージャに関する決定的な論文をいくつか書いた。そう、PCが普及する前…ずいぶん昔の話さ。(C++は何年も後に出てきたけど、好きになれなかった。もし何年も前にCの「++」版を強制されていたら、ハードウェアの道を選んでいただろうね。)
GLSは80年代初頭にCMUに移籍して…彼から「比較プログラミング言語論」の授業を受けたのを覚えてるよ。いい教師で、印象深い人物だった。当然の内容に加えて、その授業ではSNOBOLやAPLも扱っていたな。懐かしい思い出だよ。
記事で正確に言及されている通り、Lispというコンセプトは今日人気のあるどの言語よりもずっと歴史が古い。それなのに、もっと多くの人に使ってもらおうとする試みがことごとく失敗しているのは、おそらく短くて「フレンドリーな」入門書を読んだくらいじゃLispを理解するのは不可能だからだろうね。
俺が初めてCommon Lispに出会ったのは2000年代初頭の大学時代だ。熱心な先生が空き時間に無料で教えてくれて、新入生だった俺には新しいことを学ぶのが楽しかった。でも実際には、あちこちで progn を使う以外にどうコードを書けばいいのかさっぱりわからなかった。知らない人のために言うと、progn はC言語の { ... } ブロックみたいに式を順番に実行するための形式のこと。動くことは動くけど、しばらくすると、カッコだらけのひどい命令型プログラミング言語を書いているだけで、関数型プログラミングについてはほとんど学べていないことに気づくんだ。
関数型のアプローチを理解するには1年以上かかったし、短絡的な「フレンドリーな入門」なんてものより確実に時間がかかったよ。
さて、Racketの話だ。LeetCodeで日々の課題を解いている時に、対応言語として追加されたのを見つけたんだ。20年以上Lispから離れていたから、いい機会だと思ったんだけど、型コントラクトの構文にはイライラさせられたよ。これはLeetCodeのNo.1「Two sum」のコードなんだけど:
(define/contract (two-sum nums target)
(-> (listof exact-integer?) exact-integer? (listof exact-integer?))
)
どう感じるかは知らないけど、これを見た瞬間タブを閉じて二度と戻りたくなくなるよ。だから、Lispを書きたい気分でLeetCodeの課題を解くときは、まずこのゴミみたいなコードを全部消して、きれいな形に戻すのがお決まりだ。
(define (two-sum nums target) ...)
こうすれば、細かい構文の違いを除けば大学時代のLispに回帰できるし、ようやく心から楽しめるってわけさ。