見出し画像

Retro-gaming and so on

RE: 番外編 リリカルLISP終了 そして・・

星田さんがリリカル☆Lispを修了した。
おめでとうございます!

こうして、また一人、この惑星上にLisperが誕生した・・・・・・。

いやね、昔はLispやる人が増えてほしいな〜、とか思ったんだけど。
でもあんま人には薦めなくなっちゃったの。
Lispって人を選ぶんだよねぇ。いい意味でも悪い意味でも。
でも星田さんはLispに選ばれちゃったみたい。
まぁ、苫米地さんの本を読んだ、って経験が大きいんだろうけど。

さて、リリカル☆Lisp最終章。難問中の難問だと思ってたんだけど、星田さんアッサリ解いちゃったみたいね。すげぇ。
これはネタとしては何度か名前を出してるラムダ算法の発案者、アロンゾ・チャーチが提唱したチャーチ数ってのが元ネタです。
とは言っても、ホントのチャーチ数ってのはこれまた酷いんですが。
ゼロの定義は以下の通り。

(define (zero f)
 (lambda (x) x))

「団子」じゃなくって「何回関数fが作用したのか」が数を決めてる。
上は結局f(lambda (x) x)内部のxに一回も適用されてないので0です。
fが1回適用されれば1なので、結果、

(define (one f)
 (lambda (x) (f x)))

が1となり、fが2回適用されれば以下同文。

(define (two f)
 (lambda (x) (f (f x))))

とは言ってもコイツらは「関数を引数にとって」しかも「関数を返す」関数なんで何が何だか分からない。
そこでインチキしてこういう関数を作る。

(define (inc n)
 (+ n 1))

んで、次のように各チャーチ数(関数)に関数incを与えて、それが返す関数に0を与えると「何回fが適用されたか」、つまり具体的な数値が分かるわけ。

> ((zero inc) 0)
0
> ((one inc) 0)
1
> ((two inc) 0)
2
>

チャーチ数の関数を「一増やす」関数は次のように書く。

;; 1 増やす関数
(define (succ n)
 (lambda (f)
  (lambda (x)
   (f ((n f) x)))))

従って、3は2を使って次のように定義が出来る。

;; 3 の定義

(define three (succ two))

また関数incを使って確かめてみると、確かにそうなってる。

> ((three inc) 0)
3
>

足し算は1増やす関数succを使って次のように定義が可能。

;; 足し算

(define (add m)
 (lambda (n)
  (lambda (f)
   (lambda (x)
    ((((m succ) n) f) x)))))

2 + 2は次のようにして計算可能。incで確かめながら、ね。

> ((((add two) two) inc) 0)
4
>

掛け算は足し算より簡単で、こうだ。

;; 掛け算

(define (mult m)
 (lambda (n)
  (lambda (x)
   (m (n x)))))

2 × 3はこうなる。

> ((((mult two) three) inc) 0)
6
>

キリが無いんでこの辺でやめときますが(笑)、これが団子数の元ネタです。
個人的にはさすがにリリカル☆Lispでここまでやらんで良かったわ(笑)。
さすがに関数fが何回適用されたか数えるより団子数えた方がマシだしな(笑)。
上手い具合に問題をダウングレードしてくれたとは思います。
とは言っても難問だとは思うけど(ぶっちゃけ、僕も初回は解けなかった・笑)。

さて。


おっと間違えた(笑)。
こっちだ。

Clisp入れたし

おお、Clisp入れましたか。
僕も最初に触ったANSI Common Lisp処理系はClispでしたね。
遅い、って評もあるんだけど、Land of Lispで使用してる処理系だし、なんつったって、世界で一番有名なLispハッカー、ポール・グレアム愛用の処理系です。
一応説明しておくと、Clispってネイティブ・コンパイラじゃなくってバイトコード・コンパイラなんです。そういう意味で言うとJavaに近い。
つまり、Clispは仮想マシンです。他の主だったANSI Common Lisp処理系はネイティヴコード、つまり、僕らが使ってるPC用にマシン語を吐き出すんだけどClispはそういう設計にはなっていない。
ただ、それはメリットで、

  1. WindowsでコンパイルしたコードをMac/Unix/Linuxに持ち込んで、Clispがインストールされてる環境だとどこでも動かす事が出来る。
  2. ネット上で動かすのが比較的安全。攻撃を受けてもPC本体じゃなく仮想マシンがターゲットになるから。
と言う特徴がある。要はやっぱメリットはJavaに近いんです。
ポール・グレアムが作ったYahoo! Storeは元々はClispで書かれてたんだけど、恐らくその最大の理由はセキュリティです。当時から優秀なANSI Common Lispのネイティヴコンパイラはあったんだけど、それを選択しなかった理由はClispがそれらに比べて安全だったから、でしょう。仮想マシンなんで。攻撃を受けてもサーバー本体には影響が行かない。
と言うわけで、確かにバイトコードコンパイラとネイティブコンパイラを比べるとバイトコードコンパイラの方が遅い。でもあまりあるメリットもあるよ、って事ですよね。

んでだ。
ここでどうしようか、ちと悩んでたんですよね。
と言うのも、処理系があってもテキストエディタをどうするのか、って問題がある。
僕も昔、はじめてClisp触った時、テキストエディタとどうやり取りさせるんだかサッパリ分からなくって。直接インタプリタに打ち込んでたんですが(笑)、それはそれで大変なんですよね。
だからテキストエディタに付いてのTips書きたかったんだけど、さてどうすんべ。

ちなみに、一つだけ面白い事があるんで教えましょう。
ANSI Common Lispってのは電話帳みてぇにクッソ厚い仕様書で定義されてるんですが。
それはある意味、1958年の登場から1980年代通じての「ノウハウの塊」なんですよ。「開発環境はこうあるべきだ」と。
フツーはね、例えば言語処理系とデバッガとか分かれてるんです。
ところが、ANSI Common Lispって、こないだtrace見たら分かるでしょうが、「デバッガモドキ」まで言語仕様に取り込んでるの。ここまですんのか?ってくらい「言語そのもの」が色んな機能を含んでる。
1990年代からVisual BasicからはじまってDelphiとかVisual C++とか「IDE付きの」プログラム開発環境が整ってきて、またEclipseと言うJavaを初めとして使える独立したIDEが出てきて、「テキストエディタ(のようなモノ)」が複雑化の一途を辿るようになったんですが。
逆にANSI Common Lispは「言語処理系本体が肥大化する道を選んだ」最後のプログラミング言語、って言えるかもしれません。

んでね。なんでそーゆー話をしたんか、と言うと。
今となっては殆ど誰も使わんだろうけど、ANSI Common Lispにはedって言うコマンドがあるんです。
いや、勃起不全の方じゃなくって(笑)。
実はこれは「テキストエディタを立ち上げる」コマンドなんです。言語処理系自体の方からテキストエディタを立ち上げる・・・っつーのは、まぁ、ほぼねぇんだよな(笑)。ANSI Common Lispだと「ある」んだけど。text EDitorの事ですね。
んで、引数にファイル名の文字列を与えるとそれで、システムに用意されてるテキストエディタが立ち上がる。結局Windowsだとメモ帳がご丁寧にも起動すんだよな(笑)。


Linuxでの例。Clisp上で(ed "foo.lisp")と打つと、UNIX系でのデフォルトテキストエディタ、vimがファイル名foo.lispとして立ち上がる。
上でも書いたが、Windowsではvimの代わりにメモ帳が立ち上がる。
ちなみに、vimは古く、Windowsではマイナーなテキストエディタだが、反面、Mac界隈では絶大な人気を誇り、また、Lispハッカー、ポール・グレアム愛用のテキストエディタでもある。

つまり、以下解説していく事がもし「メンドくせぇ」とかなった場合、最悪でもClispからedコマンドを打って、メモ帳でLispコードを書いてClispフォルダ内に保存 -> Clispから(load "ファイル名.lisp")でソースコードを読み込んで評価、と言うプロセスは辿れる、って事です。

さて、本当の事を言うと、今現在だと、ANSI Common LispをやるならSpacemacsって言う環境に頼るのが一番なんですが・・・・・・。何故なら色々と面倒がないから、なんだけど。
ただね、別の問題が生じるんだよなぁ。

  1. 母体となるGNU EmacsのWindows版が本当に信頼できるのか怪しい。
  2. プルダウンメニューが全くないので、キーバインド操作に頼らないとならない。
  3. しかしそのキーバインド操作が変態的である。
1番は英語圏だと問題ないんだけど、日本だととにかく問題なのよね。要するにIMEの問題だ。
「俺はプログラミングでは日本語は打たない」って人ならいいけど、そうもイカんでしょ。
で、有志がWindows用にその辺の「日本語入力の問題を解決して」独自にコンパイルして配布してたりもするんだけど、なかなか大変みたいで、いつでも最新版が使える、たぁ限らないのです。
大体、せっかくUTF-8対応の処理系使うんだから、日本語打てないと面白くないでしょ?


そう、CLISPなら日本語のシンボルが使える。これはPythonには無理だ(と言うか、Pythonは比較的新しい言語の割には命名で使える文字が限られている)。
んで、Spacemacsだと2番と3番の合わせ技が酷いのね。初心者向けじゃない。
キー操作はvimが基本になってるんだけど、昔のテキストエディタって「モード切替」ってのがあって、iを叩いたら入力、Escで入力モード解除、とか良く分からんのよ(笑)。
vimを使って来たんで慣れてます、って人ならいいんだけど、いきなりこれ使えって言われてもフツーは困るだろ、と。まぁ、ポール・グレアム目指すのなら止めねぇけどさ(笑)。
まぁ、でもいずれいつかはSpacemacsでもいいかもしんない。けど今じゃねぇだろ、と。そもそもvim系の操作に慣れるのがどうしても先決になるし、それに関わってるのがストレスになってプログラミングが楽しくなくなる、とかなったら本末転倒だしねぇ。


Spacemacsだと設定ファイルに一言common-lispと書けば開発環境に必要だと思われる拡張ファイルがインターネット越しに全て自動でダウンロードされて設定される。
ANSI Common Lispの開発用ツールSLIME他、カッコ補完機能や入力補完機能、等が一式揃う。
なお、Pythonでも使えるIDEであるし、対応言語もマイナー言語を含めて多い。

と言うわけで、Windowsだとなかなか快適なプログラミング環境を探す、とか構築するってムズいんですよ。
っつーかぶっちゃけ、Lispだから、ってぇんじゃなくってそもそもMicrosoft言語以外には優しくないのです。
まぁ、そんな中でPython「だけ」が頑張ってるように見えるね。Pythonの作者、グイドも、Pythonコミュニティから離れて今やMicrosoftに就職しちゃったみたいだし(笑)。
そのうち、MicrosoftからVisual P#とか出るんかしら(笑)。

んでまぁ無い知恵絞って考えたんですが・・・・・・。

WindowsでANSI Common Lispを書く前提のテキストエディタを探すと言うと、多分これしかない。
xyzzyを推薦します。多分それが今んトコ最適解だわ。


こいつは非常に軽いテキストエディタだし、当然色んなプログラミング言語で使えるんですが・・・・・・。
実はこいつそのものが中にLisp持ってるんだわ。だからLispを書く際に余計な手間が要らないのね。最低限の面倒はxyzzyが見てくれる。
んでね。基本的な使い方としては。大体上下に画面を二分割すんの。



で、例えば下の画面にマウスでカーソル持って行って。M-x shellと打つ。
ここでM-xってのは「メタキーとxキーを同時に押した後」って意味なんだけど。
要するに「メタキー(WindowsではAltキーの事)とxキーを同時に押した後shellとタイピングしろ」ってのをM-x shellと表現します。


そうすれば下段でshell・・・ってのはUNIX用語だけど、要するにDOS窓が走るの。Windowsだとコマンドプロンプトって今は呼んでるのかしらん。
まぁ、上の写真はLinux上のWindowsエミュレータで動かしてる写真なんで、ちとカンジが違ってパッとせんかもしれんけど。
いずれにせよ、ここでClisp呼び出せば最低限の「環境」にはなるのね。まぁWindowsエミュレータじゃClisp呼び出せなかったんで写真はこれまで、ですが。

んで、まぁ最低限の体裁は整ってるんだけど、xyzzyが書いたソースファイルをどこに保存するんだ、とか、Clispがデフォルトでどのフォルダからソースファイルをロードすんだ、とかそういう問題があるじゃない。
同じフォルダで作業した方がラクだよね、って話。
そこで環境設定の話をします。
こういうのもし、やった事が無かったら「メンドくさッ」って思うかもしれない。
でもホントはWindowsでプログラミングする、って場合こういう事やらなアカンのよね。
Pythonがホント、例外的に例外で、インストーラが全部面倒見てくれるんだけど、フツーはやってくれないの(笑)。自分でやらなアカン。
っつーか、これがあるからLinuxの方がプログラミングはラクなのね。言語インストールしたら環境変数、っつーんだけど、全部面倒見てくれるし。
要するにWindowsはプログラミングするにはメンド臭い環境なのね。「ソフトウェアをあくまで買って使ってもらう」為のOSだから。そういう意味では素人に「色々とアブないプログラミングをさせない」って意味では理にかなってるんだが・・・・・・。

で、環境設定の話を書きます。大まかに言うと5ステップあります。
まず1stステップは確認、です。

1. 拡張子を見える設定にしてますか?

多分、*.csvとかCSVファイル利用したプログラム書いてたから大丈夫だとは思うんだけど、念の為。
とにかく、Windowsでプログラムを書く際には必ず拡張子が見える設定にしましょう。これ、意外とプログラミング教える人たちとかもヌケてて教えるの忘れてたりすんだわ。自分のPCで拡張子が見える状態になってるのが当たり前過ぎて(笑)。
だからそれ忘れてて、教えて!gooなんかでのプログラミング初心者の投稿内容「☓☓が保存出来ません」とか「☓☓ファイルを実行したいのに出来ません」とか見て「意味が分からん」とかなるわけよ(笑)。拡張子が隠されてるので「*.py.txt」に実はなってました、とか(笑)。想像もつかないわけ。
と言うわけで、自分のPCでは拡張子を見えるようにしておきましょう。
そうじゃなかったらコチラへ。=> Windows 10 ファイルの拡張子を表示させる方法

2. CLISPとxyzzyのフォルダは"C:\"直下に置く。
これ、もっと先に書いとくべきだったのかもしれんけど。
CLISPやxyzzyのフォルダは"C:\"直下にあった方が色々と面倒がないです。要するにね、階層が"C:\clisp-2.49\"とか"C:\xyzzy\"だった方が良い。
まぁ、コピペでフォルダ移動させるだけで済むんでいいでしょ。

3. 同じく"C:\"直下にhomeフォルダをこさえる。
プログラミング言語によってはソースファイルを保存する場所を"C:\ユーザー\<ユーザー名>\ドキュメント"にしてたりするんだけど・・・・・・。そっちはワープロとかエクセルとかのファイル用だろ?ってのがどうしても抜けない。
まぁ、個人的感情でしょ、って言われればそうなんですが。
でもプログラミング用のフォルダって「遊び場」なんで、別にあった方が良いと思うのよねぇ。
と言うわけで、Cドライブ直下にhomeと名付けたフォルダを作ります。
結果"C:\home\"の誕生だ。

4. いよいよ環境変数の設定!

まずは基本的な環境変数の設定方法から。こちらを参考にしてください。 =>
で、環境変数ってのはナンジャラホイ、って話もあるたぁ思うんだけど、ザックリ言うと「そのソフトウェアがどのフォルダにいようと呼び出せる」ように設定するものです。
例えばAフォルダにA.exeと言うソフトが入ってる。別にBフォルダがある。BフォルダからA.exeってのは「端末/DOS窓の世界じゃそのまま呼び出せない」のね。A.exeがある場所をキチンと指定せんとコマンドにならないわけだ。
フツーは僕らGUIでマウス使ってるんでバンバンフォルダ開けてはダブルクリック噛ましてるんだけど、生憎「ソフトウェアが自動で」なんかやる分にはそうは問屋が卸さない、ってワケだな。
そこで環境変数で「とあるどこからでも呼び出したいソフトの位置」をpathとして設定しておけば、どこからでもそのソフト名でそのソフトを呼び出す事が出来る、と。
とまぁそんなワケなんですが。
多分上の環境変数設定の方法に付いてのリンクで。まず最重要事項。

☆弄るのはユーザー側であってシステム側ではない。

ココ重要。下手にシステム側はイジらない。
そして、ここからやるのは。上のリンクで「編集」と「追加」の二つがあったと思うんですが。
ここでやるのは一つの編集、と二つの追加です。

  1. "C:\clisp-2.49\"はpathに追加する(編集)。
  2. 環境変数XYZZYHOMEを追加し、値は"C:\home\"にする。環境変数HOMEを追加し、それも値は"C:\home\"にする。
多分pathはPythonインストールしてると既にあるんで、編集対象ですね。Pythonのインストーラが色々と面倒見てくれてるんで、Python関係のパスだらけでしょ?
そいつら消すとマズいんで、「編集」でClispのパスを「追加」するに留めておいてください。
2は新しく二つ環境変数をそのまま追加する。XYZZYHOMEとHOMEが新しい環境変数名で、中身はどっちも"C:\home\"でいい。これでhomeフォルダはxyzzyとClispの初期設定ファイルの読み込み元になったし、いずれにせよ、プログラミングに関わる上での最重要フォルダとなった。

5. Clisp用初期設定ファイルを作ってhomeフォルダに置く。

ラストです。homeフォルダ内でファイルを右クリックで「新規作成」します。テキストファイルでいい。
で、そのファイルの名前を".clisprc"にする。「ドット」を忘れない。そしてこれは「拡張子名」だけのファイルです。
そしたらそのファイルをそれこそメモ帳ででも開いて、次のLispコードを書いて保存してください。

(ext:cd "c:\\home\\")

そうすれば、Clispが起動する度にこのファイルが読み込まれ、ロード対象のフォルダは常に"C:\home\"になります。
そうすれば、xyzzyで作ったファイルのデフォルト保存場所は"C:\home\"になり、Clispで読み込ませたいファイルの場所もデフォルトで"C:\home\"になる。
そうすれば、

xyzzyでlispファイル作成("hoge.lisp作成") => C:\homeに保存(C:\home\hoge\lisp) => clispの(load "hoge.lisp")は常にC:\homeから探す => clispで実行

と言うサイクルが出来るんで、ちっとはプログラミングはラクになるでしょう。
と「そうすればこうなる」3段階。

と言うTipsでした。

あと、前回上げるの忘れてたんだけど、Haskellと言う言語で語られてる「なぜ関数プログラミングが重要か」と言う論文があります。
高階関数を組み合わせてプログラムを作る話が書かれてるので、色々と参考にはなるでしょう。
ザーッと目を通してみてください。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「RE: 番外編」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事