Newsgroups: comp.lang.dylan
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!ix.netcom.com!netcom.com!netcom8.netcom.com!haahr
From: haahr@netcom.com (Paul Haahr)
Subject: Re: Continued confusion about identity and assignment
In-Reply-To: derway@ndc.com's message of 14 Jun 1995 21:29:10 GMT
To: derway@ndc.com (D. Erway)
Message-ID: <HAAHR.95Jun15104753@netcom8.netcom.com>
Sender: haahr@netcom8.netcom.com
Organization: NETCOM On-line services
References: <2370.9506141625@subnode.aiai.ed.ac.uk> <DERWAY.95Jun14142910@alumni.ndc.com>
Date: Thu, 15 Jun 1995 09:47:53 GMT
Lines: 159

Don Erway <derway@ndc.com> wrote:

> Look everybody, can we agree to use some standard terminology here.

Fine.  Let's try taking it from a standard reference.  I pick the Dragon
Book.  [Aho, Sethi, & Ullman 86], pages 424-6, uses these definitions:

  Call-by-value

    This is, in a sense, the simplest possible method of passing
    parameters.  The actual parameters are evaluated and their r-values are
    passed to the called procedure.  Call-by-value is used in C, and Pascal
    parameters are usually passed this way.  [...]  Call-by-value can be
    implemented as follows.

    1.  A formal parameter is trated just like a local name, so the
    storage for the formals is in the activation record of the called
    procedure.

    2.  The caller evaluates the actual parameters and places their
    r-values in the storage for the formals.

    A distinguishing feature of call-by-value is that operations on the
    formal parameters do not affect values *in the activation record of
    the caller*.  [Emphasis added.]

  Call-by-reference

    When parameters are passed by /reference/ (also known as /call-by-
    address/ or /call-by-location/), the caller passes to the called
    procedure a pointer to the storage address of each actual parameter.

    1.  If an actual parameter is a name or an expression having an
    l-value, then that l-value is passed.

    2.  However, if the actual parameter is an expression, like a + b
    or 2, that has no l-value, then the expression is evaluated in a new
    location, and the address of that location is passed.

    A reference to a formal parameter in the called procedure becomes,
    in the target code, an indirect reference through the pointer passed
    to the called procedure.

If you use these definitions -- which I'd argue are the closest we can
come to standard -- it becomes clear that Dylan uses call-by-value.
Always.  (Well, not for macros.)  Call-by-value does not say ``do not
affect values indirectly referenced by the actual parameters,'' it talks
about affecting the caller's locals.

These definitions are a bit inappropriate for Dylan, which doesn't have
an explicit notion of l- and r-values.

> Dylan does not do what the whole CS community means when we say "call
> by value".  We all mean "call by giving a copy of the value of this
> variable to the callee".

I'd be hard pressed to find that meaning in the definition above.

> The implication is that there is total break between the caller
> environment, and the callee environment - nothing the callee does to
> its argument can effect the value back in the caller environment, (in
> the absence of pointers).

Whether the actual parameters contain pointers is an orthogonal issue.

> Dylan does something very close to what the whole CS community means
> when we say "call by reference" - caller and callee each have a
> reference to a shared object.  

I think you're confusing parameter passing with values in general.  In
Pascal and C you can have immediate values which hold records, structs,
and (in Pascal) arrays.  In Dylan, you can't:  all objects have shared
(reference), rather than value, semantics.  That is, in Dylan, you don't
have the equivalent of a ``struct foo'' only a ``struct foo *''.

To understand the distinction, remember that parameter passing in Dylan
always has the same semantics as let-binding the formal parameters.  You
wouldn't expect let to copy, would you?

> All dylan, "variables" are really just names references.

I must not be following the distinction you're making here, because
that's what I thought variables were in most programming languages,
certainly including Pascal, C, and C++.  (I'm not sure where dynamically
scoped languages fit into the picture.)

> Personally, I cannot see any difference between what Dylan does and what we
> standardly refer to as "call by reference".  Anyone?

Absolutely.  Contrast this Pascal routine

  procedure swap(var x, y: integer);
    var t: integer;
    begin
      t := x;
      x := y;
      y := t
    end;

with this Dylan one

  define method useless (x, y)
    let t = x;
    x := y;
    y := t
  end method useless;

and tell again that Dylan's parameter passing is call-by-reference.
(I believe it is universally agreed upon that Pascal's var parameters
are call-by-reference.)

>  jd> Again it depends on what kinds of "identity test" are available, in
>  jd> particular on whether there's an equivalent of Lisp eq in Dylan.  (I
>  jd> don't remember off-hand whether there is or not.)
> 
> Dylan does have eq and equal, (== and =).

Actually, == is more like CL's eql:  two numbers (of a built-in
class) with the same value and class are identical, and two characters
with the same value are identical.

> At least in Mindy, they have arranged so all instances of '10' are
> both == and =.

This is required by the language.  (But 10.0 ~== 10.)

> I guess this means that for all immutable objects, if they have the
> same type, and the same value they are both =, and ==.

Users can construct their own immutable objects (using only setter: #f
slots, for example), but these do not have the semantics you described.

>  jd> No.  Ordinary, mutable objects are passed by value and are not copied.
>  jd> That's because they're (in effect) represented by a pointer.  The
>  jd> pointer *is* copied.
> 
> I think you are confused.  This is clearly *NOT* "call by value".

No, Jeff's right.

> It is almost irrelevant whether the pointer is copied.  The only
> difference is that the callee cannot change what the caller's variable
> points to.

Um, that's exactly the distinction between call-by-value and
call-by-reference.

>  jd> I must be misunderstanding something in your message, for you seem to be
>  jd> under the impression that not copying (Dylan) is less efficient than
>  jd> copying (C).
> 
> For a value that fits in a {word}, calling by not copying is much less
> efficient, because every use of the value requires an extra indirection.

Those semantics (extra indirection) are required by Dylan, unless it can
prove that the slot is not side-effected in a certain body of code, in
which case it can be optimized out.

Paul
