guile-devel
[Top][All Lists]
Advanced

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

Re: multiple return values


From: Neil Jerram
Subject: Re: multiple return values
Date: 03 Aug 2001 13:15:16 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

>>>>> "Matthias" == Matthias Koeppe <address@hidden> writes:

    Matthias> Marius Vollmer <address@hidden> writes:
    >> 
    >> The question is now, do we want to allow ignoring superflous
    >> values, or should that be an error.  I'm in favour of allowing
    >> them to be ignored.

    Matthias> I think it is a bad idea because it encourages writing
    Matthias> non-portable code: R5RS (Control Features) says that
    Matthias> "Except for continuations created by the
    Matthias> `call-with-values' procedure, all continuations take
    Matthias> exactly one value."  Clinger also calls this situation
    Matthias> (passing multiple values to single-value continuations)
    Matthias> an error in his posting.  Hence, your proposed change
    Matthias> does not make the m-v implementation more "correct".
    Matthias> [...]

I agree with Matthias.  I also noticed this clause in R5RS recently
(in the context of a multiple values version of `map' - appended below
for interest), and it seems to be pretty conclusive.  I also agree
that there is no strong reason to treat truncation to one value more
specially than, say, to two values.

    Matthias> If I have read Clinger's posting correctly, he actually
    Matthias> suggested to check for a multiple-value context by
    Matthias> looking at the `return address', i.e. at the
    Matthias> continuation of the `values' call.  I don't know if
    Matthias> that's easily possible in Guile, though.  If it is, that
    Matthias> would be a real alternative and improvement to the
    Matthias> current implementation because it would allow for proper
    Matthias> error checking without imposing runtime penalties for
    Matthias> single-value situations.

Doesn't this boil down just to a `multiple_value_continuation_p' local
variable on the stack in the evaluator, which is initialized to 0 but
set to 1 by the code that handles `call-with-values'.  Then, as long
as we've got tail recursion right, multiple_value_continuation_p will
remain set for any context that is in tail position with respect to
the `call-with-values' expression.

        Neil


(define-module (ossau map-mv)
  #:export (map-multiple-values map/mv))

(define (map-multiple-values proc arg1 . args)
  "Like @code{map} but handles multiple values from @code{proc}.
If any of the calls to @code{proc} return multiple values,
each of the multiple values is added to @code{map-multiple-value}'s
list of results.  It follows that the complete results list
may not have the same length as the lists of input arguments.

@example
(map-multiple-values (lambda (x)
                       (values x (* x 2)))
                     '(10 100 1000))
@result{}
(10 20 100 200 1000 2000)
@end example"
  (let ((arg1l (length arg1)))
    (for-each (lambda (argn)
                (or (= (length argn) arg1l)
                    (error "Lists have differing lengths!")))
              args))
  (let ((result '()))
    (let loop ((arg1 arg1) (args args))
      (if (null? arg1)
          (reverse result)
          (begin
            (call-with-values
              (lambda ()
                (apply proc (car arg1) (map car args)))
              (lambda values
                (for-each (lambda (value)
                            (set! result (cons value result)))
                          values)))
            (loop (cdr arg1) (map cdr args)))))))

(define map/mv map-multiple-values)

;;; map-mv.scm ends here




reply via email to

[Prev in Thread] Current Thread [Next in Thread]