[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Multiple values for R4RS.



Your proposal doesn't say what happens when the number of values
expected by the receiver is different from the number the generator
produces.  A simple case is when multiple values are returned and one
is expected:

	(cons (values 1 2) 3)
	=> (1 . 3)
	=> (<?> . 3)
	=> <error>

In the case of most functions (like CONS), I favor signaling an error,
but I can imagine some cases where passing multiple values as a single
parameter into a function should be permitted.

My argument stems from my discontent with Common Lisp when I have to
write code like:

	(let ((a (foo)))
	  (multiple-value-bind (b c d)
	      (bar)
	    (let ((e (baz)))
	      ...)))

when I would much prefer to write:

	(let* ((a (foo))
	       ((b c d) (bar))
	       (e (baz)))
	  ...)

Granted, this can be accomplished by extending the syntax of LET*,
which in Scheme would expand to:

	(let ((a (foo)))
	  (apply-values 
	    (lambda (b c d)
	      (let ((e (baz)))
	        ...))
	    (bar)))

but the same is not true of LET:

	(let ((a (foo))
	      ((b c d) (bar))
	      (e (baz)))
	  ...)

	-->

	((lambda (a (b c d) e)
	   ...)
	 (foo)
	 (bar)
	 (baz))

This suggests an extension of LAMBDA in which it may be specified that
multiple values can be passed in by a single parameter.  In addition
to the conciseness this permits with LET and LET*, one could also
imagine writing code with this extended LAMBDA such as:

	(define foo 
	  (lambda (a (b c))
	    (list a b c)))

	(foo 1 (values 2 3))
	=> (1 2 3)

	(foo 1 2)
	=> <error>


---PROPOSAL---------------------------------------------------------------------

(LAMBDA <formals> <body>)			essential syntax

<formals> ::=   <variable>
              | (<var/values>*)
              | (<var/values>+ . <variable>)

<var/values> ::=   <variable>			; single value
                 | (<var/values>*)		; multiple values


(LET (<binding spec>*) <body>)			essential syntax
(LET* (<binding spec>*) <body>)			essential syntax

<binding spec> ::= (<var/values> <expression>)


(VALUES . <expression>*)			essential procedure

(APPLY-VALUES <receiver> <generator>)		essential procedure

- with appropriate error messages when numbers of values mismatch.
- also suggest renaming APPLY to APPLY-LIST.

--------------------------------------------------------------------------------

Note that:
	
	(apply-values (lambda (a b c) ...) (foo))

is equivalent to:

	((lambda ((a b c)) ...) (foo))


I realize that the cost to implementors is much higher for this
proposal, but I think the power and conciseness of expression
justifies it.

Warren Harris