Macro SHIFTF

UP


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)のとき、 place1placenまでの値を読み込み保存され、 そしてnewvalueが評価され、合計でn+1個の値が用意されます。 2n+1個目の値は、それぞれplace1placenに格納されます。 それは全て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*

例外

なし。

参考

setf, rotatef, 5.1. 一般化された参照

備考

(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)

TOP, Github