guile-devel
[Top][All Lists]
Advanced

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

Re: multiple return values


From: Matthias Koeppe
Subject: Re: multiple return values
Date: Fri, 03 Aug 2001 10:47:37 +0200
User-agent: Gnus/5.090004 (Oort Gnus v0.04) Emacs/20.6

Marius Vollmer <address@hidden> writes:

> reading a article by William Clinger on comp.lang.scheme just
> enlightened me about how to efficiently and correctly implement
> multiple return values.
> 
> With that technique (see below), we can efficiently ignore superflous
> return values in places that don't expect them.  Would you like to
> have this behavior?  I.e.
> 
>     (define (mfloor x)
>       (let ((f (floor x)))
>         (values f (- x f))))
> 
> could be used in places where only a single value is expected, and the
> remainder would be ignored.
> 
> Currently, we have the incorrect behavior that
> 
>     (define f (mfloor 3.5))
> 
> will bind f to multiple values!  I.e.
> 
>    guile> f
>     3.0
>     0.5
> 
> 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.

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

Moreover, I fail to see why it would be so useful to truncate multiple
values to _one_ value.  In other situations, it would be as useful to
just take the first two values and ignore the remaining ones.  But
nobody would suggest to truncate values to the arity of the
call-with-values consumer.

I'd rather suggest to make it an error to pass multiple values to
single-value continuations.  In some key places like `define' or
`let', this error should actually be checked for.  This would actually
be an improvement over the current behavior because it helps a lot
with debugging.

> Here is how I plan to re-implement multiple values:
> 
> We define a new `multival' for use by `call-with-values' and `values'.
> This fluid is normally `#f'.  When `values' is invoked and multival is
> #f, only the first value is returned (or #<unspecified> if there are
> no values), or alternativly an error is signalled when there is not
> exactly one value.
> 
> When multival is #t, the values are returned as a list, and multival
> is reset to #f before returning.
> 
> call-with-values sets multival to #t, invokes the producer, and then
> checks the fluid.  If it is still #t, it is reset to #f, and it is
> noted that a single value has been produced.  If it is #f, a list of
> values has been returned.

I don't think this approach can work because single-value
continuations can occur within the call-with-values producer.
Consider this:

        (call-with-values 
          (lambda () 
            (let ((foo (values 2 3))) ; values called in ordinary cont.
              (values 6 7)            ; values called in ordinary cont.
              (values 4 5))           ; values called in m-v cont. because
                                      ;   of tail position
        
          (lambda (a b) ...)))

With your approach, you would have to translate the producer into
something like this:

          (lambda ()
            (let ((foo (with-fluids ((multival #f)) (values 2 3))))
              (with-fluids ((multival #f)) (values 6 7))
              (values 4 5)))
        
I'd rather stick with the current approach of having a special value
type for multiple values.

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

-- 
Matthias Köppe -- http://www.math.uni-magdeburg.de/~mkoeppe



reply via email to

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