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

multiple values and T



Here is the material taken from "T Version 3.0 Release Notes" concerning
multiple return values.  Following this material will be a short example
which demonstrates how this could be made more general.

Version 3.0 of T supports multiple return values.  This makes procedure
call and return uniform, in te sense that a procedure can be invoked with
zero or more values and can return zero or more values.

   (return {value}*) ==> {value}*                            procedure

return returns its arguments as the values(s) of the current expression.
In order to access the value(s) of a return expression the value(s) must be
bound to identifiers using either receive or receive-values.

For example,

   ((lambda () (return 1 2 3))) ==> 1 2 3

where "==> 1 2 3" denotes evaluates to the three values 1, 2, and 3.

return when invoked with no arguments returns to the calling procedure with
no value.  Thus (return) will return to its caller with no value.  It is an
error to return no value to a value requiring poisition.  For example,

   (list 'a (return)) ==> error

The idiom (return) is useful for procedures that return an undefined value and
many of the system procedures whose value(s) is(are) undefined now return no
value.  However, the procedure undefined-value may provide a more informative
error message.

   (receive-values receiver sender)                          procedure
      ==> value(s) of receiver

receive-values returns the value of applying receiver, a procedure of n
arguments, to the values returned by sender.  sender is a thunk, a procedure
of no arguments, which returns n values.

For example,

   (receive-values (lambda (x y) (list x y))
                   (lambda () (return 1 2)))  ==> (1 2)

   (receive ({ident}*) expression {body}*)                  syntax
      ==> value of body

In a receive form the expression is evaluated in the current environment
and the values returned by the expression are bound to the corresponding
identifiers.  body, which should be a lambda body, i.e. a sequence of one
or more expressions, is evaluated in the extended environment and the
value(s) of the last expression in body is returned.

The expression

   (receive (a b c) (return 1 2 3)
      (list a b c))
      ==>   (1 2 3)

is equivalent to

   (receive-values (lambda (a b c) (list a b c))
                   (lambda () (return 1 2 3)))
      ==>  (1 2 3)

Other froms have been extended in T3.0 to allow multiple return values.

   (catch identifier {body}*)  ==> value of body            syntax

The identifier is bound to the continuation of the catch form, which is now
an n-ary procedure.  This means that catch forms can return multiple values.
The continuation can be invoked only during the dynamic extent of the catch
form.  In T2 the continuation was a procedure of one argument.  For example,

   (catch x (list 1 (x 2 3) 4)) ==> 2 3

   (ret {value}*) ==> {value}*                              procedure

returns zero or more values as the value of the current read-eval-print loop.

Note:  Multiple values are implemented efficiently.  It may be more efficient
       to use multiple values than to pass continuations.
                                          
End of disccusion from the Relases Notes.

What disturbs me is the way that it does not seem to be as general as it
could be.  What I would like to propose is the ability to splice in return
values.  Here is an example:

   ((lambda (a b c q x y) ...)
    (return 1 2 3) 4 (return 5 6)).

It is possible that this capability is exactly what T Version 3.0 does.
However, there were no examples of this type so I believe this has been
overlooked.

I know that when we met in Cambridge Jonathan offered to work on multiple
values.  This is something for all of us to consider.

Dan