Macro SHIFTF
shiftf
place+ newvalue => old-value-1
place - place
newvalue - フォーム。評価されます。
old-value-1 - オブジェクト(最初のplace
の古い値)
shiftf
は、各要素の値の変更を行いますが、 まずnewvalueを最後のplace
へ格納し、 そのあと2番目から最後までのplace
の値を残りのplace
にシフトします。
もしnewvalueが格納変数より多い値を生成したときは、余分な値は無視されます。 もしnewvalueが格納変数より少ない値しか生成しなかったときは、 値のないものはnil
がセットされます。
フォームが(shiftf place1 place2 ... placen newvalue)
のとき、 place1~placenまでの値を読み込み保存され、 そしてnewvalueが評価され、合計でn+1
個の値が用意されます。 2
~n+1
個目の値は、それぞれplace1~placenに格納されます。 それは全てplaceフォームがシフトレジスタであるかのように扱われます。 newvalueは左からシフトされ、全ての値は左へひとつずつシフトされ、 そしてシフトから外されたplace1値が返却されます。
place
のサブフォームの評価については、5.1.1.1. place
のサブフォームの評価をご確認ください。
setq x (list 1 2 3) y 'trash) => TRASH
(shiftf y x (cdr x) '(hi there)) => TRASH
(=> (2 3)
x => (1 HI THERE)
y
setq x (list 'a 'b 'c)) => (A B C)
(shiftf (cadr x) 'z) => B
(=> (A Z C)
x shiftf (cadr x) (cddr x) 'q) => Z
(=> (A (C) . Q)
x setq n 0) => 0
(setq x (list 'a 'b 'c 'd)) => (A B C D)
(shiftf (nth (setq n (+ n 1)) x) 'z) => B
(=> (A Z C D) x
define-setf-expander
, defsetf
, *macroexpand-hook*
なし。
(shiftf place1 place2 ... placen newvalue)
の効果は、だいたい次と同等です。
let ((var1 place1)
(
(var2 place2)
...
(varn placen)
(var0 newvalue))setf place1 var2)
(setf place2 var3)
(
...setf placen var0)
( var1)
ただし、これは各place
のサブフォームを2度評価していますが、 shiftf
はただ一度だけです。 例えば、下記の通り。
setq n 0) => 0
(setq x (list 'a 'b 'c 'd)) => (A B C D)
(prog1 (nth (setq n (+ n 1)) x)
(setf (nth (setq n (+ n 1)) x) 'z)) => B
(=> (A B Z D) x