[R7RS+ base][SRFI-17] First, expression is evaluated. In the first form, the binding of symbol is modified so that next reference of symbol will return the result of expression. If symbol is not locally bound, the global variable named symbol must already exist, or an error is signaled.
The second form is a “generalized set!” specified in SRFI-17. It is a syntactic sugar of the following form.
((setter proc) arg ... expression)
Note the order of the arguments of the setter method
differs from CommonLisp’s setf
.
Some examples:
(define x 3) (set! x (list 1 2)) x ⇒ (1 2) (set! (car x) 5) x ⇒ (5 2)
[SRFI-210] Sets values of multiple variables at once. Expr must yield as many values as var …. Each value is set to the corresponding var.
(define a 0) (define b 1) (define c 2) (set!-values (a b) (values 3 4)) a ⇒ 3 b ⇒ 4 (set!-values (a b) (values b a)) a ⇒ 4 b ⇒ 3 (set!-values (a b . c) (values 1 2 3 4)) a ⇒ 1 b ⇒ 2 c ⇒ (3 4)
See also define-values
(Definitions).
[SRFI-17] Returns a setter procedure associated to the procedure proc. If no setter is associated to proc, its behavior is undefined.
A setter procedure g of a procedure f is such that when used
as (g a b … v)
, the next evaluation of (f a b …)
returns v.
To associate a setter procedure to another procedure, you can use
the setter of setter
, like this:
(set! (setter f) g)
A procedure’s setter can be “locked” to it. System default setters,
like set-car!
for car
, is locked and can’t be set by
the above way. In order to lock a setter to a user defined procedure,
use getter-with-setter
below.
If proc is not a procedure, a setter generic function
of object-apply
is returned;
it allows the applicable object extension to work
seamlessly with the generalized set!
.
See Applicable objects, for the details.
Returns #t
if a setter is associated to proc.
[SRFI-17] Takes two procedure get and set. Returns a new procedure which does the same thing as get, and its setter is locked to set.
When an inlinable procedure has a locked setter, generalized set!
may be inlined by the compiler. See Definitions, for inlinable
procedure definition.
A few macros that adopts the same semantics of generalized set!
are also provided. They are built on top of set!
.
Conses item
and the value of place, then sets the result to place.
place is either a variable or a form
(proc arg …)
,
as the second argument of set!
. The result of this form
is undefined.
(define x (list 2)) (push! x 3) x ⇒ (3 2) (push! (cdr x) 4) x ⇒ (3 4 2)
When place is a list, it roughly expands like the following.
(push! (foo x y) item) ≡ (let ((tfoo foo) (tx x) (ty y)) ((setter tfoo) tx ty (cons item (tfoo tx ty))))
Note: Common Lisp’s push
macro takes its argument reverse
order. I adopted this order since it is consistent with other
destructive operations. Perl’s push
function takes the same
argument order, but it appends item at the end of the array
(Perl’s unshift
is closer to push!
).
You can use a queue (see data.queue
- Queue) if you need a behavior of Perl’s
push
.
The value in place must be a list. If item isn’t already in the value in place, place is updated with the cons of item and its previous value. If item is already in the value, nothing is done.
The equivalence is checked with equal procedure. If omitted,
eqv?
is assumed.
This is similar to Common Lisp’s pushnew
, but the argument
order is flipped.
See also enqueue-unique!
and queue-push-unique!
in data.queue
(data.queue
- Queue).
(define v (vector '("a"))) (push-unique! (vector-ref v 0) "b") v ⇒ #(("b" "a")) (push-unique! (vector-ref v 0) "A" string-ci=?) v ⇒ #(("b" "a")) (push-unique! (vector-ref v 0) "A") v ⇒ #(("A" "b" "a"))
Retrieves the value of place, sets its cdr
back to place
and returns its car
.
(define x (list 1 2 3)) (pop! x) ⇒ 1 x ⇒ (2 3) (define x (vector (list 1 2 3))) x ⇒ #((1 2 3)) (pop! (vector-ref x 0)) ⇒ 1 x ⇒ #((2 3))
Note: This works the same as Common Lisp’s pop
.
Perl’s pop
pops value from the end of the sequence;
its shift
does the same thing as pop!
.
Evaluates the value of place. It should be a number.
Adds (inc!
) or subtracts (dec!
) delta to/from it,
and then stores the result to place. The default value of
delta is 1.
This is like Common Lisp’s incf
and decf
, except
that you can’t use the result of inc!
and dec!
.
Generalized form of push!
etc. Proc must be a procedure
which takes one argument and returns one value. The original value of
place is passed to the proc, then its result is set to
place.
(define a (cons 2 3)) (update! (car a) (lambda (v) (* v 3))) a ⇒ (6 . 3) (update! (cdr a) (cut - <> 3)) a ⇒ (6 . 0)
It is roughly equivalent to:
(let ((tmp0 place0) (tmp1 place1) ... (tmpN placeN)) (set! place0 tmp1) (set! place1 tmp2) : (set! placeN tmp0))
However, if place
is the form (proc arg ...)
, then
each arg is evaluated only once.
It can be used to swap values of two locations:
(let ((x (vector 1 2))) (rotate! (~ x 0) (~ x 1)) x) ⇒ #(2 1)
This is similar to Common Lisp’s rotatef
.