[comp.lang.misc] Alternatives to refs

anw@nott-cs.UUCP (11/29/88)

[Clay Phipps (>>) and Steven Ryan (>) are surprised that:
	>>	  begin int I := 0, K := 1;
	>>	  ref int Ptr := I;
	>>	  Ptr := K;
	>>	  Print (I);
	>>	  end
prints 0 rather than 1.]

	Perhaps I'm being dense, but I would have been totally astonished
had it been otherwise.  Let's take it steadily:

	int I := 0, K := 1;
		# find me some local places suitable for holding two ints,
		  label them I and K, and initialise to 0 and 1 #
	ref int Ptr := I;
		# find me some local place suitable for holding a ref int,
		  (ie, for holding a place suitable for holding an int),
		  label it Ptr, and initialise to the place (the ref int!)
		  that we labelled I #
	Ptr := K;
		# make the place that we labelled Ptr hold instead the
		  place that we labelled K #
	print (I);
		# print what I holds -- still 0, naturally.  "print (Ptr)"
		  would, of course, print 1 #

>>The reason has to do with implicit conversions involving "ref" modes

	Not really -- the only conversion in the fragment shown is that
I is implicitly converted from "a place suitable for holding an int" into
"an array [of size 1] of printable objects" before being passed to the
print procedure.

	If you want to make the "place for holding an int" that the place
labelled Ptr contains hold what the place labelled K contains, then (of
course!) you should have written "(ref int) Ptr := K".  Well, of course
that's not so clear to the uninitiated;  but nor was the idea being
expressed, and you can't expect to read arbitrarily complex Algol 68
without learning it first.  There are some excellent textbooks around
which explain all this ....

>The confusion is that at times ref is treated as pointer and other times
>as a variable. Dereferencing can run away and confuse the program as to
>which is meant.

	Neither the program nor the compiler will be confused!  Nor will
you, if you first read one of the excellent textbooks ....  Ref is neither
a pointer nor a variable;  it is a keyword used [only] in constructing
modes, and "ref somemode" always means "place suitable for holding an
object of mode somemode".  You may find the incantations used to declare
identifiers or to generate such places misleading, and if so some experts
would agree with you;  but ref is blameless!

> [suggestion for "var" and "ref" ... example including:
>           var ref int Ptr = loc ref int := address I;

	But what is "variable" about Ptr?  [Algol 68 experts:  please
don't read the next sentence!]  It is a fixed label attached to a fixed
place in the computer of a fixed "shape" ("suitable for holding a ref int").
Perhaps you mean "ref var ref int Ptr = ..."?  And what do you mean by an
"address" if "I" isn't one already?  One of the major benefits of Algol 68
was that it cleared up this confusion.  Pity that more recent languages
managed to re-introduce it.

	There was a (sensible) proposal to extend Algol 68 to allow places
to be marked "read only", "write only", etc., but that seems to be not what
you have in mind.

-- 
Andy Walker, Maths Dept., Nott'm Univ., UK.
anw@maths.nott.ac.uk

chl@r1.uucp (Charles Lindsey) (11/30/88)

In article <594@tuck.nott-cs.UUCP> anw@maths.nott.ac.uk (Dr A. N. Walker) writes:
>[Clay Phipps (>>) and Steven Ryan (>) are surprised that:
>	>>	  begin int I := 0, K := 1;
>	>>	  ref int Ptr := I;
>	>>	  Ptr := K;
>	>>	  Print (I);
>	>>	  end
>prints 0 rather than 1.]

Various people have been trying to explain this one. Personally, I would write
it as follows.

	  begin
 	  loc int I := 0, K := 1;
	  loc ref int Ptr := I;
	  Ptr := K;
	  Print (I);
	  end

The keyword 'loc' (which is legal ALGOL 68) serves to introduce a local
variable-declaration (as opposed to the identity- (or constant-) declaration
which is written
	int Zero = 0, One = 1;  ).
You may regard 'loc' as a fancy way of writing 'ref', but with the added side
effect that it actually obtains some local space to be 'ref'ed at. So you see
at once that the mode (i.e. type) of I is 'ref int', and that Ptr is a
variable to hold pointers to 'ref int' variables such as I or K, rather than
their contents. Then there should be no surprises.

The reason the keyword 'loc' is optional is that it was added at the last
moment, the original idea having been to copy the exact syntax of the ALGOL 60
variable-declaration. Personally, I always put it in, and if you leave it out
my compiler annoys you with a Warning message.

akwright@watdragon.waterloo.edu (Andrew K. Wright) (12/02/88)

In article <594@tuck.nott-cs.UUCP> anw@maths.nott.ac.uk (Dr A. N. Walker) writes:
>[Clay Phipps (>>) and Steven Ryan (>) are surprised that:
>    >>      begin int I := 0, K := 1;
>    >>      ref int Ptr := I;
>    >>      Ptr := K;
>    >>      Print (I);
>    >>      end
>prints 0 rather than 1.]
>
>    Perhaps I'm being dense, but I would have been totally astonished
>had it been otherwise.  Let's take it steadily:
>
>    int I := 0, K := 1;
>        # find me some local places suitable for holding two ints,
>          label them I and K, and initialise to 0 and 1 #
>    ref int Ptr := I;
>        # find me some local place suitable for holding a ref int,
>          (ie, for holding a place suitable for holding an int),
>          label it Ptr, and initialise to the place (the ref int!)
>          that we labelled I #

I agree that this statement should have the interpretation you give,
but the issue is confused (i think) by the declaration.  Lets separate
the two:
    ref int Ptr;        -- ignoring initialization
    Ptr := I;

Now this last statement could be assigned two possible semantics.
1. the space named Ptr is assigned the address of the space named I.
2. the space pointed to by the space named Ptr is assigned the
value extracted from the space named I.

I will the call the first one "shallow" semantics, and the second
"deep" semantics.  In general, you can have graduation of deepness
if you have more ref's involved.  The confusion arises because both
the "address of" operation and the "indirect through" operation
are implicit.

C deals with the problem by making almost everything explicit.
"address of" is always explicit, and MORE THAN ONE indirection must
also be explicit (one indirection, converting an lvalue to an rvalue, is
implicit, and always performed unless & is present (except for
arrays and functions)).  The C equivalent is
    int I;
    int *P;
    P := I;     -- is illegal
    P := &I;    -- shallow
    *P := I;    -- deep

Algol-68 deals with this problem by introducing the rule that
dereferencing is never implicitly performed on the left hand side of :=.

>> [suggestion for "var" and "ref" ... example including:
>>           var ref int Ptr = loc ref int := address I;

We have toyed with this idea in designing a new type system.
Rather than saying that "var" is a variable; however, we prefer
to say that it is very similar to "ref", but that there is automatic
devar'ing, and no automatic deref'ing.  := requires that its left
operand be of type "var something".  devar'ing is preferred where
possible.  var something can be automatically converted to ref something,
but not the other way around.  Then if you write
    var int I;
    var ref int P;
    P := I;                  -- shallow meaning, same as P := (ref int) I;
    (var int) P := I;        -- deep meaning
assignment to P by default has shallow meaning, like Algol-68.
On the other hand,
    var int I;
    var var int P;
    P := I;                  -- deep meaning, same as (var int) P := I;
    (var ref int) P := I;    -- shallow meaning
assignment to P by default has deep meaning, as
Clay Phipps and Steven Ryan expected.

This is not to say that by introducing "var" we have forgotten about
the similarity between pointers and variables exemplified by Algol-68;
we think they are similar, not identical.  "var" types allow us control
over the differences.

Comments?
Problems?  (we have a few, but I will keep them to myself since this
            posting has become long enuf)

Andrew K. Wright      akwright@watmath.waterloo.edu
CS Dept., University of Waterloo, Ont., Canada.