On Tue, Jun 21, 2016 at 01:48:27PM +0000, jmh530 via Digitalmars-d-learn wrote: [...] > Thanks to you and the others for the detailed clarifications. I think > part of the difficulty is that there are basically three things being > discussed that are all very similar: an alias to data, a pointer to > data, and a view of data.
The word "alias" is unfortunately overloaded to mean similar, but not exactly the same, things. "Alias" as used in the keyword "alias" is a compiler construct that has no real bearing on the type system. All it is, is to create a new name for something. For example, if I have: struct S { int x; } alias y = S.x; all this means is that whenever the compiler sees "y" it should act as if it has seen "S.x" instead. Well, not exactly, but basically y will refer to whatever S.x refers to in the scope of the declaration. This makes it useful sometimes for naming things that are hard or impossible to name in a different scope, for example: struct S(T) { alias ElementType = T; } S!int s; static assert(is(s.ElementType == int)); >From an outsider's POV, the template parameter T is not easily obtained, but having a convenient alias inside the scope where it *is* easily obtained, makes it readily available to outside code. None of this is related to the present topic, though. Which brings us to the second meaning of "alias", as used in the type system to mean that the same data can be reached from multiple references. At the bottom of this is pointers, and abstractions built on top of pointers. int x; int* p = &x; This sense of "alias" is usually used as a verb, as in "the pointer p aliases the variable x". Meaning, you can reach the data represented by x via the pointer p. So this is similar to the first meaning of "alias" in the sense that p is kinda like a different name for x, but semantically it's not quite the same thing, because alias in the first sense is a compile-time concept of having one identifier being treated as though it were another, whereas alias in the second sense here is a runtime concept, in that the data x exists somewhere in memory, say location L, and the pointer p happens to contain the value L, so using p we can find x in memory without actually referring to x directly in the code. Now, what's the distinction between int*, const(int)*, and immutable(int)*? Or, for that matter, const(int*) and immutable(int*)? To understand this, it's useful to think of the data being pointed to distinctly from the pointer. All of the above pointers point to some int sitting somewhere in memory. Let's say there are two ints, sitting in memory locations L1 and L2, respectively. When we declared the two ints, we specified the first one as simply 'int', meaning it's mutable. So memory location L1 contains an int that can be modified. Let's say the second int is declared as immutable(int), so L2 contains an int that, once initialized, cannot be modified. (In this respect, there is no difference if we declared const(int) instead, since either way nobody can modify the value once it's initialized.) Now, int* is a pointer to (mutable) int, so it can never point to L2. If the language allowed that, it would break the contract that L2 cannot be modified. Similarly, immutable(int)* is a pointer to immutable(int), so it can never point to L1. However, const(int)* can point to both L1 and L2, because const(int)* just means that you cannot use *this* pointer to modify the data, but somebody else who has a mutable reference (i.e., int*) pointing to the same data, may use it to modify the data. So in short: int* means "pointer to an int that anybody can modify" immutable(int)* means "pointer to an int that nobody can modify" const(int)* means "pointer that cannot be used to modify the int, but can be used to read the int" So if you have an int* in hand, you know that the memory location it points to is mutable, and if you have an immutable(int)* in hand, you know that the memory location it points to is immutable (to everybody, not just you). However, if you have a const(int)* in hand, all you know is that *you* can't modify the data (or more precisely, you cannot use this particular pointer to modify the data), but it says nothing about whether the data itself is actually modifiable or not. What about const(int*) and immutable(int*)? Here, thanks to transitive const in D, the const and immutable applies both to the pointer and the data pointed to. So const(int*) means that the data cannot be modified through this pointer, and also that you cannot modify this pointer itself. (But somebody with a mutable reference to this pointer may change what it points to.) Similarly, immutable(int*) means that the data cannot be modified by anybody (whether through this pointer or otherwise), and the pointer itself also cannot be modified by anybody. T -- Many open minds should be closed for repairs. -- K5 user