#:g1: setqはprogの中だけで使うというスタイルの提案

Posted 2021-11-30 16:05:39 GMT

Lisp一人 Advent Calendar 2021 1日目の記事です。

ここ数年ニッチなテーマでアドベントカレンダーを開催したりしなかったりしています。 今年は何も準備していなかったので、どうせ一人で開催だし見送ろうかと思いましたが、普段からLispブログのネタだけは50位のストックがあるので、この機会に成仏させることにしました。
ちなみに割とどうでも良いようなネタしかありません。

setqprogの中だけで使うというスタイルの提案

近年、純粋関数型言語の擡頭で、世間はやれデータはイミュータブルが良いやらなんやらと喧しいですが、関数型プログラミングの先駆けたる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はより抽象度の高い繰り返し構文等に置き換えられ、前時代的なものになりました。

setqprogの中だけで使うというスタイル、というのは、この前時代的なprogを使うことによって、代入という行為をしているコードをさらに古臭く見えるようにする、というのが狙いです。

実際に書くとどういう風になるか

基本的にletの中でsetqsetfをしている場合に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

comments powered by Disqus