Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!sunybcs!geller From: geller@sunybcs.UUCP Newsgroups: comp.lang.lisp Subject: Multiple Return values in Common Lisp. Message-ID: <1560@sunybcs.UUCP> Date: Tue, 2-Dec-86 11:52:34 EST Article-I.D.: sunybcs.1560 Posted: Tue Dec 2 11:52:34 1986 Date-Received: Wed, 3-Dec-86 06:39:00 EST Sender: nobody@sunybcs.UUCP Reply-To: geller@sunybcs.UUCP (James Geller) Organization: SUNY/Buffalo Computer Science Lines: 117 I don't consider myself a great expert on Common Lisp, but it seems to me that the idea of "multiple return values" of Common Lisp is ill conceived. This is not to say that one does not need multiple return values, but that they should be used in a conceptually different way. Lets assume that the function "extent" returns an x value as major return value, and a y value as "multiple". Now lets assume that I have an operation that needs both, the x and the y value. In the current implementation of multiple return values I would have to create a list of all return values and then access the x and y coordinates from this list. It would be much more reasonable to create a calling convention that permits to access the different return values at different points. Example: (defun extent (rectangle-name) ;; This returns the x-length of the rectangle "rectangle-name" ;; It also returns the y-length as a multiple ;; return value. .......) (defun perimeter (rectangle-name) ;; This uses both, the "normal" and the "multiple" ;; return value. It computes the perimeter of the ;; rectangle "rectangle-name". (+ (* (extent/1 rectangle-name) 2) (* (extent/2 #*) 2))) Now what is the postulated meaning of above notation? (extent/1 rectangle-name) is a call to the "extent" function. It returns the major return value only. That is, it returns the "x-extension" of the rectangle "rectangle-name". (extent/2 #*) returns the "multiple" return value of THE SAME ARGUMENT as extent/1. So in fact the extent function is NOT executed again, but the second return value of the last call was stored at the time when extent/1 was called, and the call to (extent/2 #*) just retrieves this value. The symbol /1 is meant to retrieve the major return value. /2 is meant to retrieve the second return value. #* is a pseudo argument that inhibits reexecution of the function. I should mention that I am not particularly in love with my notation. Any suggestion for a better notation will be accepted. Its just that I had to write a number of functions lately that would have benefited from above mechanism. ------------------------------------------------------------------- The above concept is also applicable to "normal" functions, although this is a minor concern for me at the current moment. Example: (defun square-of-hard-to-get-number (argument) (* (long-computation argument) (long-computation #*))) People who don't hesitate to use a "setq" will not understand why I don't write: (defun square-of-hard-to-get-number (argument) (* (setq dummy (long-computation argument)) dummy)) But I have been raised in the tradition of functional programming. So I end up writing (defun helper (argument) (square-variant (long-computation argument))) (defun square-variant (hard-to-get-number) (* hard-to-get-number hard-to-get-number)) Or a lambda expression with the same effect. This is really an unnecessary inconvinience. Jim P.S. Should this subject have been brought up already, my apology. I missed some news over diverse breaks. =========================================================================== || UUCP : {cmc12,hao,harpo}!seismo!rochester!rocksvax!sunybcs!geller || || ...{allegra,decvax,watmath}!sunybcs!geller || || CSNET : geller@buffalo || || ARPA : geller%buffalo@csnet-relay || || BITNET : geller@sunybcs || || US MAIL: James Geller/ Dept. of Comp. Sci./ SUNY at Buffalo/ || || 226 Bell Hall/ N.Y. 14260 || =========================================================================== o o o o o o o