> Just because it is an immutable value doesn’t mean it needs to live on the stack.
Right. But the context of the example made me imagine it probably was -- since I would likely reject out-of-hand any new language that always allocated variables on the heap.
> Yet you can absolutely write: > String str = "hello,"; > str += "world!"; So
it's "immutable" for some lawyerish definition which does me no good.
`str` is a mutable reference to an immutable object. You can make the
reference point to something else, but the object being pointed to is
immutable, so eg if you pass it to a function, that function cannot change it
under you. If you want to make the reference immutable, declare it as final. I
don't think understanding the difference between a pointer and the value it
points to is lawyerish.
> But it's clearly not what people mean when they talk about pointers (or references) being mutable.
The semantics of a programming language is what it is, not what you want it to be, unless you explicitly choose a language that allows you to express exactly what you mean.
> But nobody does that. Chances are someone on the team takes a shit about unnecessary memory copies
It’s not just performance. In any moderately complicated C++ program, you will want a function to mutate its argument, and this falls apart.
Sure, you can write in a pure functional style with immutable data structures, but I wish you luck implementing an immutable data structure with asymptotically reasonable performance without using pointers of some sort.
> The immutability is already implied by the 'let' and 'var'.
The immutability of the binding and that of the value are different concerns. let and var are about the binding's mutability, trying to munge them together only ends up in tears.
> The proposal is similar to proposing the following declaration in C:
> That's why D has an `immutable` qualifier, giving the optimizer to do optimizations assuming it does not change.
Which optimizations are enabled by immutable data? I can think of constant folding. Is the data statically allocated in a read-only page?
> For a famous example, Fortran assumes two arrays never overlap. In C/C++ they can. This is the source of a persistent gap in performance between Fortran and C/C++.
What sort of optimizations does this assumption enable? Does it allow the compiler to freely reorder or parallelize the code?
C assumes that pointers to different types are never equal. This is incompatible with common systems programming concepts such as type punning. Even something simple like reinterpreting some data structure as an array of uint8_t can make the optimizer introduce bugs into the code. Notably, the Linux kernel is compiled with strict aliasing disabled:
> That is integer arithmetic, not pointer arithmetic.
Yeah, but I did say: "which operation could any C compiler disallow in practice: converting from pointer to integer, arithmetic on integers, or converting from integer to pointer?"
If C/C++ compilers keep breaking pointer arithmetic in the game of exploiting undefined behavior for optimizations, people are going to start doing pointer arithmetic with integers when they need it. And they do need it sometimes, for debuggers, profilers, memory checkers, JITs, garbage collectors, shared memory, and so on.
C++ does not really permit this. It is incredibly hard to do type punning from void* without hitting UB. You really are only allowed to access objects through their names according to their lifetimes.
Here (https://www.youtube.com/watch?v=IAdLwUXRUvg) is a fun talk that involves trying to do a pretty basic kind of arbitrary memory access and concluding that it is simply not possible in C++.
> the same people who think that it's okay that memcpy(0, 0, 0) is undefined behavior.
I am curious about this particular example. How does that ever make sense, where do you have that?
I'd accept that it would be nice to have memcpy(p1, p2, n) with valid pointers p1 and p2 to still be defined when n=0, because maybe n is variable and might work out to be 0 in some cases, which you then don't need to treat specially. I don't know whether that case is defined or not.
But in the case where either p1 or p2 are NULL, the memcpy will be illegal no matter what n is, so if p1 or p2 are variable you always have to check them anyway, and to run into the memcpy(0, 0, 0) case you would actually have to special case n=0 when p1 or p2 were NULL, which makes no sense.
Unless 0 is actually a valid address (kernel code with identity mapping at 0, simple platforms), but then NULL becomes a whole different beast.
> Your proposal replaces my use of an array with two things, a pointer (as before) and a length. This is not too helpful, because I already could have done that if I'd wanted to.
C doesn't have a reasonable way of doing that. I know my proposal works, because we've been using it in D for 20 years.
> This is pretty basic C++/computer architecture stuff.
The C rules for integer type promotions are incredibly hard to reason about. They should have just banned implicit conversions from the beginning. This is not super basic stuff.
even if I use a magnetic needle to change the bits in my RAM ? :)
reply