2.1 multi-value binds
Peter Norvig
Multiple values are a good solution because they are unobtrusive until they are needed.
Most of the time when we are [for example] using round, we are only interested in the integer value. If round did not use multiple values, if it packaged the two values up into a list or structure, then it would be harder to use in the normal cases.

Introducing the Binding of Multiple Values via the DIRM and DRM
graphic
 
 
2.1.1 How are local multi-value-bind's done in Common Lisp and Dylan?
Dave Moon
These are equivalent Common Lisp and Dylan program fragments:
[Common Lisp]
(multiple-value-bind (a b c) (f x)
    (g a b c))
[Dylan]
let (a,b,c) = f(x);
  g(a,b,c);
Peter Norvig
in
Quote from his textbook Paradigms of "Artificial Programming":
Sometimes we want a single function to return more than one piece of information. Of course, we can do that by making up a list or structure to hold the information, but then we have to go to the trouble of defining the structure, building an instance each time, and then taking that instance apart to look at the pieces.
Consider the function round. One way it can be used is to round off a floating-point number to the nearest integer. So (round 5.1) is 5. Sometimes, though not always, the programmer is also interested in the fractional part. The function round serves both interested and disinterested programmers by returning two values: the rounded integer and the remaining fraction:
     (round 5.1) => 5 .1
There are two values after the => because round returns two values. Most of the time,
multiple values are ignored, and only the first value is used. So (* 2 (round 5.1)) is 10, just as if round had only returned a single value. If you want to get at multiple values, you have to use a special form, such as multiple-value-bi nd:
(defun show-both (x)
    (multiple-value-bind (int rem)
      (round x)
    (format t "~f = ~d + ~f" x int rem)))
>  (show-both 5.1) 5.1 = 5 + 0.1
fun-principal
type into the Dylan interactor:
graphic
The round method is part of Dylan's
define method say-rounding-values ( x :: <real> )
    let ( integer, remainder ) = round(x);
    format-out( "\n  %=  =  %d  +  %= \n\n",
               x ,  integer, remainder );
  end;
=> No values
say-rounding-values (5.1);
=> No values
Annotation about the Dylan interactor:
The dylan interactor return results via constant bindings (readonly bindings), which means within the playground the results can be reused via their binding name. Playground results are named via an integer which is prefixed by a dollar-sign. This reflect the Dylan convention to prefix module constant bindings (readonly bindungs). So the playground writes internal something like
    define constant $0  = result item
In case of multiple return values each value get associated to a constant binding.
Annotation about say-rounding-values
The call of  say-rounding-values the  method format-out opens a command window as outwindow, but note that format-out might buffer its content until it reaches a linebreak, \n. So if nothing is print in the output window make sure your output string ends with a linebreak.
Output window
graphic
2.1.2 How are multi-value-bind's done?
John Whittaker
I'm not sure what I'm doing wrong here.  I wanted to return two values from a function that computes solar positions--the right ascension and declination of the sun.  Both are <floats>. 
When I tried interactively testing this function, it would only return 1 value.  I must be missing something simple, but I don't get it.  
[...]
I've included the source for illustration:
[...]
define method compute-solar-position
    ( epoch-day :: <integer> ) =>
    ( results :: false-or( <astro-position>))
  // Now pre-compute the important values based on epoch day
  // ...
  // compute eccentric anomaly in radians
  // ...
  // compute solar true longitude
  // ...
  // compute solar ecliptic rectangular coordinates
  // ...
  // now convert these to equatorial,
  // rectangular coordinates
  let eq-x-sun = x-sun;
  let eq-y-sun = y-sun * cos( ecliptic-obliquity );
  let eq-z-sun = y-sun * sin( ecliptic-obliquity );

  // Finally, compute right ascension and declination
  let right-ascension
    = atan2( eq-y-sun, eq-x-sun );
  let declination      
    = atan2( eq-z-sun, sqrt( eq-x-sun ^ 2  + eq-y- sun ^2));

  values( right-ascension, declination );
end method;
Jonathan Bachrach
The problem is that you have defined compute-solar-position to return only one value (i.e., => (results :: <astro-position>) ).
Dylan (unlike CL) will discard extra values if less values are defined than are actually returned (and pad values with falses if more are defined than are actually returned).
You can use #rest in the values specification if you want a varying number of return values (e.g., => (#rest results :: <astro-position>) ).
2.1.3 How are multi-values return by a method?
Peter Norvig
You can write functions of your own that return multiple values using the function val ues, which returns its arguments as multiple values:
fun-principal
type into the Dylan interactor:
(values 1 2 3)
=>$8 = 1
     $9 = 2
     $10 = 4
 
 
2.1.4 how to capture an unknown number of multiple return values into a sequence?
On Thu, 2 Dec 1999, Bruce Hoult wrote:
> In article <slrn84bbs3.7hq.neelk@brick.cswv.com>, neelk@alum.mit.edu wrote:
> > ... how do I capture an unknown  number of multiple return values into a sequence? 
> >   listify(values(5,9)) => (5, 9) // a list with two elements
> >   listify(values(1,2,3)) => (1, 2, 3) // a list with 3 elements
> >   listify(values()) => #() // a list with no elements
>
> OK, I think I'm confused about what you want.
> listify is trivial to write:
>    define method listify(#rest args)
>       args;
>    end method;

You mean

  define method listify (#rest args)
    as(<list>, args)
  end;

since IIRC the type of the #rest argument is <sequence>, not necessarly <list>.

> You can't pass the result of values() to it -- it wants actual arguments.
> You can capture the results of values() into a list with:
>    let (#rest x) = values(1,2,3,4);
> If you do this then you don't need listify().
Right, so may be listify should be
  define macro listify
    { listify ( ?vals:expression ) }
   => { let (#rest temp) = ?vals;
        as(<list>, temp) }
  end;
Hugh