Subject: Re: Q:reference values
From: Erik Naggum <erik@naggum.no>
Date: 1996/03/15
Newsgroups: comp.lang.lisp
Message-ID: <3035869054132995@arcana.naggum.no>

[CMSC 420]

|   I'm writing my first LISP program.  I understand that function
|   arguments are generally local variables, such as
|   
|   (defun sum (x y z) (setq z (+ x y)))
|   
|   Normally, the summed value is the return value.  Is it possible to keep
|   the summed value in z?  In C, one would use a reference, such as
|   
|   void sum (int x, int y, int& z) { z = x + y; }
|   
|   I know I could do this by making z global and not putting z in the
|   argument list, but I don't want to.

references are necessary in a language that supports only one return value
from functions, but their existence has certainly allowed a new breed of
abuse of language constructs.

references in C++ (not C) introduce "in out" arguments, if I can borrow
terminology from Ada, except that an Ada system can implement them by
making the assignments in the caller, which is clean.  references in C++
wreak havoc with the argument evaluation process, and requires that the
compiler treat each function uniquely.  in Lisp, you have only two kinds:
either all the arguments are evaluated when called, or none.

I think the way you use this feature in C++ is a clear example of abuse.

1. special variables

in Lisp, you have special variables, which can cause one function's
variables to be modified by another, but these are by name.

    (defun caller ()
      (let ((z 0))
	(declare (special z))
	(sum 1 2)
	z))

    (defun sum (x y)
      (declare (special z))
      (setq z (+ x y)))

(caller) now evaluates to 3.

if you have (defvar z 0), (caller) still evaluates to 3, but the global z
is unchanged.  if you call (sum 1 2) directly, the global z is changed.

2. macros

being able to call a function to write to a random variable is nice, but we
don't do that in Lisp.  instead, when there is a need to write to a place,
we use generalized setter functions via `setf'.  there already exists a
macro to increment a generalized place, `incf'.  you could write `sumf':

    (defmacro sumf (place &rest operands)
      `(setf ,place (+ ,@operands)))

this will work for lexical variables, as well.  it also allows such forms
as

(sumf (aref array 3 2 4) 1 1 2 3 5 8)

which will set the value of the array element [3,2,4] to the sum of the six
first Fibonacci numbers.

now, this is not a good use for the macro facility, IMNSHO, even in an
interpreted language.

also note that functions are generally not "void" in Lisp.  if you insist,
you can use the final form (values) which indicates zero return values.

#<Erik>
-- 
the Internet made me do it