lisp
ポエム
ネタ
NucoDay 19

え、もしかしてまだLispやってないやついるの!?

Nuco Advent Calendar 19日目の記事です。

はじめに言っておきますがこの記事はただのネタなのであしからず。

Lisp知ってる?

Lispはクールです。最高にクール。
どんくらいクールかって?Japanese Hegh-Tech Toiletにはさすがに及ばないね。
Lispは確かにJapanese Toiletの便座ほどあったかくはない。
むしろ展開後のマクロでバグを生み出すと元々のコードとかけ離れすぎて何のバグだか全くわからないときがある。
Lispは答えを教えてくれない。なんて冷たいやつだ。少しはヒントくれてもいいじゃないか。
まあ、しかし、そんなところもLispはクールだ。
俺はLispのそういうところも気に入っている。

Lisp知らない人は一度は書いてみた方がいい。
むしろ今時Lisp書いたことないってヤバイ。
クラウドのメールサービスが当たり前の今の時代に伝書鳩でも使ってるくらいにはヤバイ。
ちなみに鳩は1000km離れていても巣に帰れるらしい。鳩の帰巣本能ヤバイ。
そんなことはともかく、とにかくすぐにでも使ったほうがいい。君も鳩みたいにクールになれる。急に1000km離れた場所に放り投げられても平気さ。

どこがクールなの?

基本のキ、だけどリストだね。リストが最高にクール。
リストって何かって?ああ、そもそもLispのデータには2種類しかないんだ。
リストか、リストじゃないものか。
どうだい?簡単だろう?Lispはとってもシンプルなんだ。
え?そんな幼稚なトートロジーで誤魔化すなって?なんだよ、非Lisperってのはせっかちな生き物だな。
まあ、たしかにLispを始めとするラムダ計算を起源とする関数型言語は、
チューリングマシンを起源とするC言語のような命令型言語よりもパフォーマンスに難があるかもしれない。
『何がしたいか』よりも『どう動くべきか』にフォーカスしているから、マシンのパフォーマンスを限界まで使えるのは命令型のほうかもな。
しかし、マシンの性能を限界まで使えるC言語のプログラマなんてめったにいないし、最近のLisp処理系も優秀だから実装・最適化の方法次第ではほとんどパフォーマンス差はないと言っていいだろう。
俺が言いたいのは君たちはCPUがキャッシュメモリから命令をフェッチするのも待てないくらいせっかちってことさ。

リストの話に戻ろうか。
たしかに命題:A or (not A)は常に真だ。そんな言葉遊びなんてもう聞き飽きたさ。
けどLispのデータがリストとリスト以外の2種類ってのは本当さ。
リスト以外のデータ構造をアトムって言うんだ。

  • 数値
  • 文字
  • nil

これ以外にもあるが、処理系に依存する。まあ、興味があったら調べてみてくれ。
リストはアトムもしくはリストを束ねたものを指す。
ほら、簡単だろう?Lispはこんなにもシンプルなんだ。

リスト

ここでひとつ言い訳させてくれ。
実はLispにはリストを構成する要素としてペアってやつがいる。
順序付きの対になったデータのことだ。
作り方は簡単で

(cons 1 2)
> ( 1 . 2 )

consという関数でペアをつくることができる。
俺が何を言い訳したいかと言うと、Lisperの中にはペアをリストとする派とペアはリストに含めない派がある。
この辺は多少ややこしいから、ペアはリストってことにしてくれ。
さっきの章で言い切ってしまったから許してほしい。
リストとリスト以外しかないって言いたかっただけなんだ

このペアの左側の要素をcar, 右側の要素をcdrと呼ぶ。
carとcdrは関数名でもあるので、同名の関数で要素を取り出すことができる。

(car (cons 1 2))
> 1
(cdr (cons 1 2))
> 2

どうだいとっても簡単だろう?
そしてこのペアを再帰的に連ねることで任意の長さのリストを表現できる。

(cons 1 (cons 2 (cons 3 '())))
> ( 1 2 3 )

リストの終端は'()という空のリストにする。
賢い人は気づいただろうけど、これがさっき言い訳した理由だ。
リストの終端を空のリストにする、と決めると、ペアだけどリストじゃないものが存在してしまう。
まあ、いい。とりあえず話を進めさせてくれ。
俺のLisp愛はこんなものではないが、今日の所はリストの話ができればいいだろう。

再帰の美しさ

プログラマってのは再帰が好きなんだ。
いや、正確にはプログラマの中にはとんでもなく再帰が好きなやつがいる。
プログラマ以外にはそんなやついないだろう。
実は再帰はプログラム以外にも使われている。え、知らないって?
いや、君が再帰のプログラムを書いたことがないプログラマだとしても必ず君は再帰に触れている。
どこでだって?目と口と耳さ。これは絶対だ。
むしろ目、口、耳のいずれかで君たちは必ず再帰に触れている。
いいから早く教えろって?俺が脳から情報をフェッチするのも待てないのか君たちは。
ああ、フェッチは終わったんだが、今デコード中だもう少し待ってくれ。
そろそろexecuteしようか。

再帰的頭字語はご存知だろうか。
Qiitaのこんなクソ記事読んでる君たちはさぞかし好奇心が旺盛だろうから知ってるだろうな。
PHPが何の略か知ってるかい?
Peace and Happiness through Prosperityじゃないぞ、それは別のPHPだ。そっちじゃない。
正解は『PHP: Hypertext Preprocessor』だ。
ほらさすがにPHPは見たことあるし、言ったこともあるし、聞いたこともあるだろう。

え、そもそも略す前からPHPって入ってるじゃないかって?
そろそろ読んでる人たちはこの茶番じみた言い回しと進行に飽きてきただろう?同感だ。
それこそが再帰的頭字語だ。
PHPという名前の由来は再帰的なんだ。

実はコンピュータ・サイエンス界隈には結構このような略語が(ジョークも含めて)たくさんある。

  • Linux is not unix
  • npm is not an acronym
  • YAML Ain't Markup Language

おそらく全てご存知だろう。
そう。ハッカーやgeekなやつらは再帰が好きなんだ。
いや、再帰が好きだから彼らはgeekなんだろうか。
まあ、そんなことはどうでもいい。

ちなみにこのAdvent Calendarの主催である株式会社Nucoという会社。
まあ、できたばっかだから誰も知らないだろうけど、実はNucoの社名も再帰的頭字語だ。
会社のWebサイトのトップに書いてある、

Nuco Incs. unlocks cognition of Innovative next civilization.
というダサいキャッチコピーは再帰的頭字語になっている。

Nuco Incs. unlocks cognition of Innovative next civilization.
最後のドットまで含めて頭文字を結合すると、Nuco Inc.になる。
大文字やドッドまで含めているところが実にクールだろう?

まあ、話を再帰に戻そう。
Lisp、中でも俺が1番好きなのはSchemeという言語だが、
こいつは言語仕様の隅々に再帰の心が根付いている。
むしろ再帰しない方が書きづらい。最初は慣れないけど段々クセになってくる。
気づいたころにはforループって何が嬉しいかったんだろうって思えてくる。

クイックソートもこんな感じで書けてしまう。

(define (qsort lst)
    (if (null? lst)
        lst
        (append 
            (qsort (filter (lambda (x) (< x (car lst))) (cdr lst)))
            (list (car lst))
            (qsort (filter (lambda (x) (>= x (car lst))) (cdr lst))))))

クールだ…
まあ、意味はわからなくていい。いたって普通のクイックソートだ。
再帰は数学的帰納法に似る。美しい。
初期状態と、n番目とn+1番目の関係を定義すれば完成する。
何をするかではない、クイックソートの本質そのものを記述するとそのまま動くんだ。
なんて不思議なんだろう。

まとめ

全然まとまってないけどまとめる。
Lispはクールだ。
全然伝えきれなかったけど再帰の美しさについて思うがままに語ることができただけで満足だ。

みんな気づいてるかもしれないけどこの記事はネタだ。
ぶっちゃけ俺はそんなにLispに詳しくもない。
実務で使ったことはない。趣味で軽く書く程度だ。
けどLispが好きなのは本当だ。書いてて楽しい。
けど実は周りに全くLisperがいない。とっても寂しい。Lispの良さについて語りたい。
いや、あれは語るものじゃない感じるものだ。

もしLispに少しでも興味が湧いたら是非処理系をinstallしてみて欲しい。簡単だ。
Lispはプログラミングそのものの考え方を変えてくれる。

いつかまたLispについてQiitaで語ろうと思う。
読んでくれてありがとう。

こんなクソ記事書いてごめんね!!!!