[racket] Multiple return values

From: Markku Rontu (markku.rontu at iki.fi)
Date: Fri Dec 16 16:47:54 EST 2011

On Fri, Dec 16, 2011 at 3:15 PM, Matthias Felleisen <matthias at ccs.neu.edu>wrote:

>
> Does Racket blindly inherit from Scheme because of history?
>
> No, Racketeers choose what to take over and what to leave behind.
>

Great, I'm waiting for the fruits of the labour with great anticipation and
gratitude ;)


>
> Why are multiple values useful?
>
> Multiple values enable a smooth functional style where pedestrian
> programmers may have to use clumsy package-unpackage or, worse, imperative
> style. This improvement shows up especially in loops. Here is a concrete
> example from a recent program I wrote:
>
>
I'll keep this short since it's bed-time :)

Why are multiple return values better than e.g. lists? You can still mix
the order of the return values. Only thing you get is guaranteed right
number of values. But, this also makes your functions less flexible. You
are not able to add any new values because every call site must be fixed,
even if the change by itself is backwards compatible (e.g. only adding more
values). Doesn't sound like a meaningful difference. However mixing
collections and semantically different values is just bad design. Can't
prevent people from shooting their own legs except maybe in classroom.

Typical case in e.g. Java is to have a pair of Request & Response classes
for passing parameters and receiving return values. These are as close as
Java can get to named parameters and return values. You will not be able to
accidentally mix the order of the parameters or return values. You may have
sensible optional / default values. You have co-,  contravariance and
backwards compatibility for many changes of the interface. Sounds good,
doesn't it? just the syntax is Java so you'll grow old typing your solution
:) What do you think about that as a practice?

This was just something I think about these days. In Clojure side I use
maps quite much with the predictable ups and downs. For Racket I might go
with structs, if they had better support for immutability/copying, and I
think the situation is improving in this area.

What I have in mind is for example something like this.
calculate-statistics would return named return values of #:min and #:max
and compiler would check that these are ok at the call sites. Now if the
calculate-statistics also returns #:median then it doesn't matter that I
don't use it in this case. It's not a bug.

(let# ((#:min min #:max max (calculate-statistics (list 1 2 3 4 1 5 2 3 5 0
3 11))))
    ; do something with the min and max
    (do-something min))

Possibly could get rid of the extra typing when you don't want/need to
rename:

(let# ((min max (calculate-statistics (list 1 2 3 4 1 5 2 3 5 0 3 11))))
    ; do something with the min and max
    (do-something min))

(define (calculate-statistics data)
    ; do the work
    ...
    ; return some named values
    (return #:min min #:max max #:average average #:median median))

And again the predictable minimization:

(define (calculate-statistics data)
    ; do the work
    ...
    ; return some named values
    (return# min max average median))


I might try implementing something like that when I come up with a decent
syntax.

-Markku
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20111216/876000ad/attachment.html>

Posted on the users mailing list.