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

Re: small Q



In article <398EA566.8AB90683@dial.pipex.com>, jt 
<gkt37@dial.pipex.com> wrote:

> Hi all,
> 	I've looked in the DRM for this and not found it. 
> 
> In a statement like 
> 
> 	let (x, y) = values (y, x)
> 
> what is being returned by the 'values' function? What sort of structure
> is it?

It's not a structure or a list.

When you say in C++ ...

  float pythagorus(float x, float y){
    return sqrt(x*x + y*y)
  }

  float foo = pythagorus(3.0, 4.0);

... what sort of structure are 3 and 4 passed in?  They aren't.  There's 
no structure.  A structure would imply an implicit order to them.  It 
would imply packing and unpacking.  It would imply that the values have 
addresses and that if the called function took the address of x then it 
could add sizeof(float) to get the address of y.  None of that is true 
in C++ [1], or in Dylan.


> Or is it merely a shorthand for something that the compiler
> unfolds into a sequence of individual assignments?

That's closer to it, but it's not assignment.  It's "binding", the same 
as happens to arguments in function calls.

Here's what it really means.  Suppose your code looks like this:

----------------------------------------------------------
method ()
   // do a whole lot of stuff, including creating x and y

   let (x, y) = values(y, x);

   // do a whole lot more stuff using x and y
end;
----------------------------------------------------------


What it actually means is:


----------------------------------------------------------
method ()
   // do a whole lot of stuff, including creating x and y

   let rest_of_the_function = method (x, y)
      // do a whole lot more stuff using x and y
   end;

   rest_of_the_function(y, x)
end;
----------------------------------------------------------

Alternatively, this could be written (creating and immediately using an 
anonymous method) as:


----------------------------------------------------------
method ()
   // do a whole lot of stuff, including creating x and y

   method (x, y)
      // do a whole lot more stuff using x and y
   end (y, x);
end;
----------------------------------------------------------


Basically, in Dylan, each use of "let" creates a new environment 
extending from the "let" to the end of the block.

In other related languages, such as Scheme, each "let" is actually 
written with its own set of brackets and you quickly get really deeply 
nested visually for no good reason.  the nesting still exists in Dylan, 
you just can't see it.


Don't worry that "let" is inefficient because it creates and uses a 
function.  The compiler is smarter than that.  It sees that the function 
is only used once and inlines it and you end up with the efficient code 
that you'd expect in any other language.


To be technical, (and tie this in with another thread), when you say...

  let (x, y) = 

... you create a "continuation" that expects more than one value.  When 
you say...

  values(y, x)

... you pass more than one value to the continuation.

-- Bruce

[1] unless you use ... in the argument list, in which case the VARARGS 
macros have to work.  But how they work is unspecified and non-portable 
-- they have to work, but the compiler writer doesn't have to tell you 
*how*.



Follow-Ups: References: