From ... From: Erik Naggum Subject: Re: Q:reference values Date: 1996/03/15 Message-ID: <3035869054132995@arcana.naggum.no>#1/1 X-Deja-AN: 142925695 references: <4ia0qs$ktv@hecate.umd.edu> organization: Naggum Software; +47 2295 0313 newsgroups: comp.lang.lisp [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. # -- the Internet made me do it