[comp.lang.scheme] How to pass parameter by reference in scheme?

zql4991@acf5.NYU.EDU (Zhiqing Liu) (03/02/91)

The Subject has told what I want.  Thank you.

--Zhiqing Liu (liuz@cs.nyu.edu)

jinx@zurich.ai.mit.edu (Guillermo J. Rozas) (03/02/91)

In article <1519@acf5.NYU.EDU> zql4991@acf5.NYU.EDU (Zhiqing Liu) writes:

   Path: ai-lab!snorkelwacker.mit.edu!usc!zaphod.mps.ohio-state.edu!wuarchive!rice!uupsi!cmcl2!acf5!zql4991
   From: zql4991@acf5.NYU.EDU (Zhiqing Liu)
   Newsgroups: comp.lang.scheme
   Date: 2 Mar 91 05:43:41 GMT
   Organization: New York University
   Lines: 3

   The Subject has told what I want.  Thank you.

   --Zhiqing Liu (liuz@cs.nyu.edu)

It depends on exactly what you mean.  If you want to pass an object
that can then be mutated by the callee and the mutation visible to the
caller, you can just pass it normally, since all objects are passed by
reference in Scheme.  Of course, not all objects are mutable.

If what you mean is that you want to pass a VARIABLE so that the
callee can mutate the variable's value for the caller, you are out of
luck.  Scheme always passes arguments by value (but the objects passed
are themselves references).

On the other hand, if you really need to do this (see below), you can
pass a procedure of one argument (the new value) that when invoked
will set the original parameter.  For example:

(define (write-line obj)		; Lisp's PRINT
  (newline)
  (write obj)
  (write-char #\space))

(define (test)
  (let ((my-local-x 23))
    (write-line `(my-local-x ,my-local-x))
    (effect! (lambda () my-local-x)
	     (lambda (val) (set! my-local-x val)))
    (write-line `(my-local-x ,my-local-x))))


(define (effect! fetch store!)
  (let ((val (fetch)))
    (store! (* val val))))

This is not quite passing a variable by reference.  It is closer to
Algol 60's call-by-name, and mimics some of its implementations.  If
you use this pervasively, you will notice subtle differences with
passing parameters by reference (e.g. Jensen's device).

An alternative is to put your values in data structures (cells, boxes,
pairs) and pass those around.  Since you can't get the syntax to work
right anyway, this may be better and will really mimic
pass-by-reference.

The other question is why you would want to pass a variable by
reference.  Although this is a common way to do things in Pascal and
C, it is typically used mostly for aggregates (structures, records,
arrays, strings), and you get the same effect in Scheme by passing
them (the references) by value.  I suggest that you rethink your task
in a way that does not require you to pass references to variables.
Often the resulting programs are clearer and easier to understand.
Effects should not be used spuriously.

gyro@cymbal.reasoning.COM (Scott Layson Burson) (03/04/91)

   Date: 2 Mar 91 15:17:50 GMT
   From: "Guillermo J. Rozas" <jinx@zurich.ai.mit.edu>

   [...]

   This is not quite passing a variable by reference.  It is closer to
   Algol 60's call-by-name, and mimics some of its implementations.  If
   you use this pervasively, you will notice subtle differences with
   passing parameters by reference (e.g. Jensen's device).

What is Jensen's device?  This sounds interesting.

-- Scott

raja@copper.ucs.indiana.edu (Raja Sooriamurthi) (03/04/91)

gyro@cymbal.reasoning.COM (Scott Layson Burson) writes:

>   This is not quite passing a variable by reference.  It is closer to
>   Algol 60's call-by-name, and mimics some of its implementations.  If
>   you use this pervasively, you will notice subtle differences with
>   passing parameters by reference (e.g. Jensen's device).

>What is Jensen's device?  This sounds interesting.

Jensen's device is a technique to parameterize procedures using 
call-by-name parameter passing. The below Algol 60 code [from
Horowitz's book] is an example

real procedure sigma (x, j, n);
   value n; real x, integer j, n;
   begin real s;
    s := 0;
    for j := 1 step 1 until n
      do s := s + x;
    sigma := s
  end

By default everything is passed by name in Algol 60 and an explicit
declaration is needed for call-by-value (as in value n)

sigma(A(i), i, 10) returns the sum of the 1st 10 elements in A
A(1)+A(2) ... A(10)

The sum of squares of elements as well as the dot product of two
vectors could be obtained by:

sigma (A(i)*A(i), i, 10) and
sigma (A(i)*B(i), i, 10)


While Jensen's device was an illustration of how procedures could be
parameterized, I feel Scheme's 1st class procedures offer a better
mechanism for parameterization.

- Raja

---
Raja Sooriamurthi                          |   Computer Science Department
raja@cs.indiana.edu	                   |       Indiana University