Just exactly how does Scheme make that association between formal parameters and actual arguments? For example, suppose we have the following.
(define foo (lambda (x) (printf "entering foo x is ~s~%" x) (set! x 23) (printf "exiting foo x is ~s~%" x))) (define y 14) (define x 12)
Let's look at various ways we can call foo.
(foo 12) (foo (* 12 (+ 3 5))) (foo (if (> 5 (* 2 3)) 4 6)) (foo '(a b c)) (foo y) (foo x) (foo #\a) (foo #t) (foo (vector 1 2 3))
In each of the above cases, Scheme evaluates the actual argument, and makes it possible for foo to refer to the evaluated argument by the name x. That's what you see from the first (printf .. x). When (set! x 23) is executed, the local name x is made to refer to the atom 23. Nothing in the top-level data area is affected.
x is a local variable initially referring to the value of the actual argument. set! just changes this binding of the local variable x.
(define bar1 (lambda (x) (printf "entering bar1 x is ~s~%" x) (vector-set! x 1 23) (printf "leaving bar1 x is ~s~%" x))) (define bar2 (lambda (x) (printf "entering bar2 x is ~s~%" x) (set-car! (cdr x) 23) (printf "leaving bar2 x is ~s~%" x))) (define y (vector 1 2 3)) (define x '(a b c d))
Run some experiments. At the very least, apply bar1 to y and bar2 to x. Can calls to bar1 and bar2 modify the data accessible at top-level?
In this sense, Scheme appears to call by reference. When structured data is passed to a function, the formal parameter of the function is bound to the same data structure as exists in the caller's area. If you set! the formal parameter, you don't affect the caller's area at all -- you merely bind a new value to the local variable. But the more "surgical" operations, like set-car! and vector-set! can have effects visible in the caller's area.
Hand in a description of your experiment, your Scheme code for the
experiment, your results, and your conclusions.