% Macro SHIFTF
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
x => (2 3)
y => (1 HI THERE)
(setq x (list 'a 'b 'c)) => (A B C)
(shiftf (cadr x) 'z) => B
x => (A Z C)
(shiftf (cadr x) (cddr x) 'q) => Z
x => (A (C) . Q)
(setq n 0) => 0
(setq x (list 'a 'b 'c 'd)) => (A B C D)
(shiftf (nth (setq n (+ n 1)) x) 'z) => B
x => (A Z C D)
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
x => (A B Z D)