I didn't mean implicit dereference on member access, but rather implicit dereference in most non-pointer contexts. For example, suppose you have:
INT x := 0
REF INT p := x
p is a pointer here ("name" in Algol-68 parlance). Now if I want to read x via p, I can just write something like:
p + 1
No dereference operator - because + is not defined for names, the implicit dereferencing is applied (it works for multiple levels, too - REF REF INT would have been dereferenced twice).
On the other hand, the left side of := does not implicitly dereference; instead, it requires the operand to be a REF, and rebinds it. So I could do:
INT y := 1
p := y
and now p references y instead of x. If I wanted to actually mutate x, I'd have to dereference explicitly on the left side, which you do by casting, removing as many REFs as needed.
It all is actually somewhat more consistent than C, in that in C, they had to come up with that whole "value category" thing for expressions - lvalue, rvalue etc - that is orthogonal to its type. E.g. if you have "int x", the reason why you can use x on the left side of assignment is because it's an lvalue, while something like 123 is an rvalue; but the type is just int for both. In Algol, this is reflected in the type - when you say:
INT x := 1
this is actually syntactic sugar for:
LOC INT x := 1
which is in turn sugar for:
REF INT x = (LOC INT := 1)
where LOC is an operator that's kinda like a typed version of alloca() - i.e. LOC INT returns a value of type REF INT that is allocated on the stack (there's also HEAP, which is the equivalent of C++ "new", but garbage-collected). So all mutable variables actually have type REF T, and := requires the left operand to be a REF (and changes what it refers to).
OTOH if you write something like this:
INT x = 1
then x is just a binding, not a name; its type is just INT; and therefore it does not have a valid type for the left operand of assignment. Which means that technically all variables in Algol-68 are immutable - it's just that some of them can be bound to values that are names, and the name can then made to reference a different value.
On the other hand, the left side of := does not implicitly dereference; instead, it requires the operand to be a REF, and rebinds it. So I could do:
and now p references y instead of x. If I wanted to actually mutate x, I'd have to dereference explicitly on the left side, which you do by casting, removing as many REFs as needed.It all is actually somewhat more consistent than C, in that in C, they had to come up with that whole "value category" thing for expressions - lvalue, rvalue etc - that is orthogonal to its type. E.g. if you have "int x", the reason why you can use x on the left side of assignment is because it's an lvalue, while something like 123 is an rvalue; but the type is just int for both. In Algol, this is reflected in the type - when you say:
this is actually syntactic sugar for: which is in turn sugar for: where LOC is an operator that's kinda like a typed version of alloca() - i.e. LOC INT returns a value of type REF INT that is allocated on the stack (there's also HEAP, which is the equivalent of C++ "new", but garbage-collected). So all mutable variables actually have type REF T, and := requires the left operand to be a REF (and changes what it refers to).OTOH if you write something like this:
then x is just a binding, not a name; its type is just INT; and therefore it does not have a valid type for the left operand of assignment. Which means that technically all variables in Algol-68 are immutable - it's just that some of them can be bound to values that are names, and the name can then made to reference a different value.