This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: values (Re: R5RS)



> > Anyway, ML handles this whole issue much more gracefully than Scheme.
> > Calls and returns are symmetrical: they both carry exactly one value.
> > But then they have very clear, terse ways to make that one value a
> > tuple.  Mission accomplished.  And no call/cc involved.
> > 
> > What I'd like is a way to call a function with only as many arguments
> > as it expects.  That is, I've got five arguments I could pass, but if
> > the function only takes three, that's cool, just pass the first three.
> > Then, I could apply this to `values', and return only as many values
> > as the caller expects.  So I could have a division function which
> > returns the remainder too, but only if the caller was prepared for two
> > return values.
> 
> Well... if you only called functions with one argument in Scheme,
> you'd end up using either lists or vectors a lot. As long as you don't
> use null?/length on lists, or vector-length on vectors in the function,
> you would just ignore the extra arguments. Or, of course, you can test
> for extra arguments. The same is true in reverse.
> 
> Actually, I just realized we already have a special syntax for that...
> (define (func . args))

Going cheerfully but completely off-topic: sure.  But I don't consider
using Scheme's data structures as containers for arguments and return
values to be practical, because it's so inconvenient.  It's simply
nicer to write

    (define (fetch type source) ...)

than

    (define (fetch . args)
      (let ((type (car args))
            (source (cadr args)))
        ...))

I mean, really.  Whereas in ML, it's just

    fun fetch (type, source) = ...

The ( , ) syntax is *not* specifically for function arguments.  It's
the syntax for building tuples.  The thing after the function name
`fetch' is a pattern, and whatever value you pass to the function gets
matched against that pattern.  So what an invocation of `fetch' like

    ... fetch (unsigned_32bit_int, stdin) ...

really means is, "Build a tuple containing a type and an input port,
and pass that as the sole argument to the function fetch."  fetch will
then disassemble the tuple.

A decent ML compiler will, I assume, turn this into the same code
you'd get for C.  There's no need to actually construct the tuple.
So the same trick works for returning multiple values.  If I say:

   fun divide (dividend, divisor) = (dividend / divisor, dividend mod divisor)

Then I can say:

   let val (quotient, remainder) = divide (a, b)
   in ...

You get multiple return values in a completely natural, consistent,
and convenient form.

Confession: I've never actually written a single line of code in ML,
so if I've gotten something wrong, please forgive me.  But I'm pretty
sure the general ideas are correct.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]