Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!uunet!mcvax!ukc!castle!etive!lfcs!db From: db@lfcs.ed.ac.uk (Dave Berry) Newsgroups: comp.lang.misc Subject: Re: Language Tenets (too long) Message-ID: <2696@etive.ed.ac.uk> Date: 3 Aug 89 17:31:08 GMT References: <57125@linus.UUCP> <1989Jun24.230056.27774@utzoo.uucp> <1207@quintus.UUCP> <1406@l.cc.purdue.edu> <1989Jul17.184707.415@maths.nott.ac.uk> <1223@quintus.UUCP> Sender: news@etive.ed.ac.uk Reply-To: db@lfcs.ed.ac.uk (Dave Berry) Organization: Laboratory for the Foundations of Computer Science, Edinburgh U Lines: 65 In article <1223@quintus.UUCP> pds@quintus.UUCP (Peter Schachte) writes: > >The problem with multiple returns is filling out the semantics. As I >see it, there are two basic ways to handle this: > > 1. multiple results are packed up into a single structure to be > returned. To complete the semantics of this, you only need > to specify the semantics of passing such a structure as > argument to a function (or primitive like +). The ML/Hope approach is to have a tuple type. For example, divrem could return values of the type "int * int". Components can be selected by pattern matching or by selector functions. In Standard ML the syntax is "#1 (x divrem y)" to select the first result of x divrem y. Multiple arguments to (uncurried) functions don't exist; you have to create a tuple and pass that, e.g. "plus (2, 3)". Of course, if the "plus" function immediately breaks down the tuple by pattern matching the compiler should optimise away the tuple creation. You can also pass a tuple argument to an infix operator by temporarily negating its infix status, e.g. "(op +) (x divrem y)". One advantage of tuple types over C structures is that you don't have to declare special types - they're just there. > 2. The other approach is to treat multiple results as separate > things. I am a bit skeptical of Pop-2's approach: > > foo(divrem(x,y)) > > (where divrem returns both quotient and remainder, and foo > takes two arguments) calls foo with x/y and x%m as its two > arguments. It may be pure prejudice, but I'm uncomfortable > having two arguments to a function come from the same > expression. The equivalent expression in ML passes a single value around, but this will be optimised away. This is just as flexible as Pop-2, but perhaps you find it easier to cope with? (In some cases Pop-2's stack manipulation primitives may be more flexible than ML). > In any case, it's not terribly useful, since > there's a good chance I'll want the arguments in the other > order, or I'll want another argument between them, or > something. It doesn't handle all cases, but I find it useful. Of course you can assign the multiple returns to identifiers in ML, as in "let val (a, b) = x divrem y in ... end". It's nice not to have to do this when it's not needed. >It seems to me that the cleanest way to handle multiple results is to >just always put them into variables. And this is better done by passing >pointers to where to put the results than by muddling the semantics of >expressions with multiple returns. If you already have pattern matching then multiple results doesn't complicate the semantics at all. Dave Berry, Laboratory for Foundations db%lfcs.ed.ac.uk@nsfnet-relay.ac.uk of Computer Science, Edinburgh Uni. !mcvax!ukc!lfcs!db Rhetoric 101: Use of "scare" quotes and the phrase "so-called".