Subject: Re: Pass by reference
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 2000/11/17
Newsgroups: comp.lang.lisp
Message-ID: <8v30kj$60rs$1@fido.engr.sgi.com>
Erik Naggum  <erik@naggum.net> wrote:
+---------------
| * Nils Goesche <nils.goesche@anylinx.de>
| | I never understood what `call by name' means.
| 
|   It means that the full expression in the caller is evaluated in the
|   callee, instead of actually passing in the object so evaluated.
|   ...
|   The idea is that you should be able to modify the lexically named
|   place in the caller from the callee as if you _were_ the caller.
|   Very clever implementation techniques are required to implement this
|   insanity correctly and usefully...
+---------------

Which, interestingly enough, brings us back around to Lisp & Scheme,
since in many Algol implementations call-by-name was implemented by
passing the addresses of little pieces of code in the caller that would
implement the lexical environment and the evaluation of the argument form
in that environment, actually two addresses per argument -- a 0-arg "getter"
and a 1-arg "setter". These little pieces of code were called "thunks"
[see <URL:http://www.tuxedo.org/~esr/jargon/html/entry/thunk.html> for
a more detailed etymology], and the term survives today in Lisp & Scheme
meaning a closure of zero arguments.

By the way, Erik's example of calling "foo(i,a[i])", where args are
call-by-name and "foo" changes the value of its first arg, is usually
known as "Jensen's Device":

    <URL:http://www.cs.sfu.ca/~cameron/Teaching/383/PassByName.html>
    <URL:http://carbon.cudenver.edu/~traup/sp00/lecture/23.html>
    <URL:http://www.math.grin.edu/~rebelsky/Courses/CS302/99S/Outlines/
	 outline.36.html>
    <URL:http://www.cir.nus.edu.sg/~dkiong/compilers/98/03-229.html>

In Lisp, one might define a Jensen's Device generalized summation
function like so:

    > (defun jsum (item-thunk index-setter start end)
        (loop for index from start below end
	  do (funcall index-setter index)
	  summing (funcall item-thunk)))
    > 

Then you might use it to sum an array like this:

    > (defvar v1 #(0 1 2 3))
    > (let (i)
        (jsum (lambda () (aref v1 i))
	      (lambda (x) (setf i x))
	      0
	      (length v1)))
    6
    > 

But the "item-thunk" can easily be more complex. For example,
to do a dot-product between two vectors:

    > (defvar v1 #(0 1 2 3))
    > (defvar v2 #(7 5 -4 6))
    > (let (i)
        (jsum (lambda () (* (aref v1 i) (aref v2 i)))
	      (lambda (x) (setf i x))
	      0
	      (length v1)))
    15
    > 


-Rob

-----
Rob Warnock, 31-2-510		rpw3@sgi.com
Network Engineering		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043