#:g1: たまに便利な(setf apply)/(setf values)

Posted 2018-12-19 10:04:13 GMT

Lisp SETF Advent Calendar 2018 19日目 》

今回は、たまに便利な(setf apply)/(setf values)を解説してみたいと思います。

(setf values) | VALUES Forms as Places

(setf values)はそこそこ使われているかと思いますが、Common Lisp(1984)の時代から知識の更新がない年配の方々がmultiple-value-setqしか知らないような場面に遭遇することもままあります。
(古い書籍で勉強してしまったので知らなかった、ということもあります)

multiple-value-setq的な使い方

(let (q r)
  (setf (values q r) (floor 1 2))
  (list q r))(0 1) 

psetqpsetf的な使い方

(let ((a 0) (b 1))
  (setf (values a b) (values b a))
  (list a b))(1 0) 

(setf values)は他のsetfの場所と複合できるのも便利です

(let ((x (list 0 1)))
  (setf (values (car x) (cadr x))
        (values (cadr x) (car x)))
  x)(1 0) 

(setf apply) | APPLY Forms as Places

こちらは、Common Lisp(1984)からありますが、配列を多用する人以外は使う機会もないからか、それほど知られていない機能です。

添字のリストだけあって、それを適用したい、ということはあるのですが、(setf apply)arefを組合せれば可能です。

(let ((subs (list 2 1 0)))
  (setf (apply #'aref *a* subs) 42)
  *a*)
→
#3A(((0 0 0) (0 0 0) (0 0 0))
    ((0 0 0) (0 0 0) (0 0 0))
    ((0 0 0) (42 0 0) (0 0 0))) 

規格では、arefbitsbit(setf apply)の組合せは保証されていますが、他は、処理系依存です。
というのも、(setf fn)は必ずしも関数である必要はないためで、マクロで実装されている場合、applyできない、ということになるからです。

ユーザー定義の#'(setf fn)関数であれば、applyが適用できるので(setf apply)も可能です。

まとめ

(setf values)はもっと知られても良いかなと思っています。
ANSI Common Lispと、それ以前のCLtL2、CLtL1は結構違ってますので、仕様の参照/勉強では、ANSI Common Lisp規格を元にした文献を参照しましょう。


HTML generated by 3bmd in LispWorks 7.0.0

comments powered by Disqus