Posted 2021-11-30 16:05:39 GMT
Lisp一人 Advent Calendar 2021 1日目の記事です。
ここ数年ニッチなテーマでアドベントカレンダーを開催したりしなかったりしています。
今年は何も準備していなかったので、どうせ一人で開催だし見送ろうかと思いましたが、普段からLispブログのネタだけは50位のストックがあるので、この機会に成仏させることにしました。
ちなみに割とどうでも良いようなネタしかありません。
setq
はprog
の中だけで使うというスタイルの提案近年、純粋関数型言語の擡頭で、世間はやれデータはイミュータブルが良いやらなんやらと喧しいですが、関数型プログラミングの先駆けたるLISPは極初期からこのあたりのプログラミングスタイルの使い分けをしていました。
具体的にいうと、当時のFortran等の繰り返しや代入スタイルでコードを書けるようにするためのprog
形式が用意されていて、go
(goto)、return
(飛び出し)、set
/setq
(代入)は、prog
の中でのみ使えるというものでした。
また、基本的に式は値を返すものなので、値を返さない式が続く場合も基本的にprog
の中で書いていました(progn
の前身のprog2
は存在しましたが)。
prog
が導入された意図ですが、はやはり1960年代初頭の当時のコンピューター上での効率を考えてのことだったようです。
この辺りの事情を今風に表現するなら、純粋関数型プログラミングの内部に手続き型プログラミングのためのDSLを標準装備していたという感じでしょうか。
その後、1968年あたりのPDP-6 LISP(MACLISP)で、さらに効率を追求されることになり、全面的に浅い束縛が導入された結果、prog
の中での限定利用だったsetq
は大域的に利用できるようにもなり今に至ります。
ちなみにそれまで大域変数の宣言には、cset
/csetq
という、Common Lispでいうdefconstant
のようなものがありましたが、setq
に置き換えられてしまいました。
そして、さらにCommon Lispになってprog
はより抽象度の高い繰り返し構文等に置き換えられ、前時代的なものになりました。
setq
はprog
の中だけで使うというスタイル、というのは、この前時代的なprog
を使うことによって、代入という行為をしているコードをさらに古臭く見えるようにする、というのが狙いです。
基本的にlet
の中でsetq
、setf
をしている場合にprog
で置き換えれば良いのですが、変数宣言だけして、初期化はボディ内でsetq
する、という風に書くとさらに古臭くできます。
(let* ((x ...)
(y ...))
(setq x ...)
(setq y ...)
ans)
(prog (x y)
(setq x ...)
(setq y ...)
(return ans))
ちなみに、prog
は変数宣言節と同じ深さでまっすぐにインデントを揃えるのが古くからの習わしです(1970年あたりの古いコードを読んでみましょう)
■
HTML generated by 3bmd in LispWorks 7.0.0