Scheme: Defining Familiar Operations on Variables

This page provides Scheme definitions for some operations on variables familiar from other languages.

If your favourite language provides a variable operation you don't see here, let me know.

Requirements

We use the following to implement the operations:

(define-syntax define-simple-syntax
  (syntax-rules ()
    ((_ (name arg ...) body ...)
     (define-syntax name (syntax-rules () ((name arg ...) (begin body ...)))))))

Update value

Replace a variable's value with a modified version.

The following works for any operation (so is already more powerful than what can be done in Java, C, C++, Python, etc):

; (set!! op v a ...)
;   set v to (op v a ...) and return v
(define-simple-syntax (set!! op v a ...) (set! v (op v a ...)) v)

; Example
(define x 2)
(set!! + x 3) ; x is now 5
(define l '(1 2 3))
(set!! reverse l) ; l is now '(3 2 1)

The following define the well-known arithmetic versions from Java, C, C++, Python, etc. Notice our versions allow multiple arguments.

(define-simple-syntax (+= a ...) (set!! + a ...))
(define-simple-syntax (-= a ...) (set!! - a ...))
(define-simple-syntax (*= a ...) (set!! * a ...))
(define-simple-syntax (/= a ...) (set!! / a ...))

(define-simple-syntax (++ a) (+= a 1))
(define-simple-syntax (-- a) (-= a 1))

; Example
(define x 2)
(+= x 3) ; x is now 5
(+= x 4 9) ; x is now 18
(-- x) ; x is no 17

Post-increment/decrement versions of ++ and -- could also be defined.

Address and Call-by-reference

In C (but not Java nor Python) one can take the address of a variable, usually to pass it to a function for call-by-reference. The address is used to get or set the value of its associated variable.

We model the address of a variable as an overloaded procedure that when called with no argument returns the value and when called with an argument sets the variable to the argument.

;;; (& var) => a procedure p with
;;;              (p): return value of var [i.e. var]
;;;              (p val): update var to be val [i.e. (set! var val)]
(define-simple-syntax (& var)
  (let ((p (lambda args (if (null? args) var (set! var (car args))))))
    p))

; Example
(define (swap x y) (let ((temp (x))) (x (y)) (y (temp))))
(define x 2)
(define y 3)
(swap (& x) (& y)) ; x is now 3, y is now 2