For Gauche 0.9.15Search (procedure/syntax/module):

Next: , Previous: , Up: Core syntax   [Contents][Index]

### 4.4 Assignments

Special Form: set! symbol expression
Special Form: set! (proc arg …) expression

[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)
```
Macro: set!-values (var …) expr
Macro: set!-values (var … . varn) expr
Macro: set!-values var expr

[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).

Function: setter proc

[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.

Function: has-setter? proc

Returns `#t` if a setter is associated to proc.

Function: getter-with-setter get set

[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.

The intention of this procedure is, according to the SRFI-17 document, to allow implementations to inline setters efficiently. Gauche hasn’t implement such optimization yet.

A few macros that adopts the same semantics of generalized `set!` are also provided. They are built on top of `set!`.

Macro: push! place item

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`.

Macro: push-unique! place item [equal]

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"))
```
Macro: pop! place

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!`.

Macro: inc! place :optional delta
Macro: dec! place :optional delta

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!`.

Macro: update! place proc

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)
```
Macro: rotate! place0 place1 … placeN

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`.

Next: , Previous: , Up: Core syntax   [Contents][Index]

For Gauche 0.9.15Search (procedure/syntax/module):