#:g1: SETFってなに?

Posted 2018-11-30 17:05:36 GMT

Lisp SETF Advent Calendar 2018 1日目 》

Lisp SETF Advent Calendar始まりました。
数年に一度Lisp系でニッチなAdvent Calendarを催したりしていますが、最近あまりニッチなことはしていませんでした。
その反動なのかLisp SETF Advent Calendarですが、ニッチすぎたかもしれません。
ちなみに、過去のニッチなAdvent Calendarには下記のようなものがあります。

SETFってなに?

さて、setfについての簡単な説明です。
プログラミング言語の代入構文にも様々ありますが、左辺に変数名だけでなく、配列の場所であったり、リストであったりが記述できるものがあります。

x := x + 1
a[x] := y + 1
a, b, c := list(0, 1, 2)
...

右側にはどんな値でも置けるのですが、左側に置いて意味を成すものを考えると、値を代入できる場所の指定/参照、となることが多いようです。
Lispのsetfとは、値の読み書きの場所について一般化し、値の読み出しのフォームと同じ見た目のフォームで書き込みも表現しようというものです。

setfは、

(setf 場所 値)

という形式ですが、「場所」には、変数名や値をアクセスする記述を使用できます。
一番身近なリスト操作のcarで説明すると、

リストのcar読み出しフォーム

(setq x (list 0 1 2 3)

(car x) → 0

リストのcar書き込み

(setq x (list 0 1 2 3))(0 1 2 3)

(setf (car x) 42) → 42

x → (42 1 2 3)

となります、Algol風に書けば、

car(x) := list(0, 1, 2, 3)

となるでしょうか。
carで読み出して来た場所に、値を代入するという意図が表現できているかと思います。
リストの場合は、配列アクセスの表現にかなり近いので自然な拡張に思えます。

SETFFが気になる問題

長い歴史を持つLispでは、名前の由来を最早誰もはっきり説明できない関数が結構あります。
実は、setfもそんな名前の一つです。 代入だからsetは良しとして、fはなんだろう、というのはFAQでもありますが、Common Lispのsetfの由来は、L Peter Deutsch氏の論文A LISP machine with very compact programsまで遡ることができます。

代入関数であるsetが変数名だけでなく関数フォームを取れるようにしよう、というのがアイデアの骨子ですが、

setを拡張して、

(set '(fn arg1 ... argn) 42)

と書けるようにし、次に同様にsetq版も考えて、
setqは、set+quoteが由来

(setq (fn arg1 ... argn) 42)

と書けるように拡張。しかし、これでは関数フォーム全体をクォートしてしまい引数が評価されないのが実用上不便ということで、関数名だけクォートするものを考案。

(setfq (fn arg1 ... argn) 42)

この当時のLISP(INTERLISP系)にバッククォートがあれば、

これがCommon Lispでいうsetfと同じもので、(SETFQ (fn argl ... argn) newvalue) which quotes the function name and evaluates everything else.と表現されています。
ということは、setを使えば、

(set (list 'fn arg1 ... argn) 42)

と書けるということでしょうか。
それはさておき、つまりFfunctionを意図していたようですが、一番流布しているのはFField説、次にForm説あたりかなと思います。

ちなみに、やたらとクォートの扱いについて細かいと思う人もいるかと思いますが、L Peter Deutsch氏のバックグラウンドであるINTERLISPでは引数が評価されるものと、されないもの二種(q付きとqなし)が大抵用意されているので、引数評価について敏感だったのでしょう。
Common Lispでは、setsetqの関係ですが、qquoteを意味しているものとしてはsetqが唯一の生き残りです。
なお、setfqqはどっかに飛んでいってしまったようです。

今後は、setfのアイデアが最初に登場したと思われるLISP 2の解説、Lisp Machine Lispでの発展あたりについて書いたり、数あるsetfの定義構文を全部解説してみようかなと思います。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus