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.