On Monday, 28 January 2019 at 15:16:54 UTC, Steven Schveighoffer
wrote:
It will inspect the allocated length from the GC if the array
is appendable from the beginning. So it's not always going to
reallocate.
e.g.:
string x = "abc".idup;
auto app = x.appender;
app ~= "xyz"; // does not reallocate.
-Steve
Fair enough.
My use case is simply the standard usecase of Appender: I want
to build up an array in a way that reduces GC churn. Maybe
it's an array of structs that contain const members that I'll
serialize to JSON and send on a socket. In that case, I know
for a fact that no references will hang around past the
serialization. That's what clear _is for._ I don't see why
this would be different with const or immutable data; if you
hold references past .clear being called you're in trouble
*anyways.*
Right, this does seem like a big limitation. Keeping with the
spirit of how slices don't own the memory in question, Appender
is being conservative with what it doesn't know.
I wonder if it may be more appropriate to instead of preventing
clear() on immutable/const arrays, to make it @system. Or maybe
call it something different "dangerousClear" or something ;)
There definitely should be some way to fail if clear is called
on an array that was passed into the constructor.
But I'm still not sure we should allow overwriting immutable
memory without a cast, even in @system code.
My problem is this.
const and immutable are *not* well supported in the standard
library at the moment. What I want is that I can use the idioms
of the stdlib, semantically, in a way that lets me *not care*
about const or immutable, that lets me express the patterns I
want without having to worry about whether some type deep inside
my code, a dub library, or phobos itself decided to declare a
field immutable.
Appender covers two usecases: "capacity caching" and "memory
reuse." Both of those usecases have two const variations:
"possibly immutable" and "mutable".
mutable capacity caching | mutable memory reuse
---------------------------+---------------------
immutable capacity caching | immutable memory reuse
But instead of cutting between capacity caching and memory reuse,
down the middle, Appender cuts between mutable and immutable,
left to right. I think this is a symptom of a broad negligence of
constness as a first-class property - constness works sometimes,
and it's nice if it does, but it can't be *relied* on to be well
supported. This makes using const in D an eternal uphill
struggle. Why even go to all the trouble to make a new major
version of the language just to introduce constness, if it's not
going to be treated as a first-class concern? I don't want to
have to sprinkle static if(isAssignable!T) everytime I want to
use a library type. If Phobos offers me as generic a data
structure as Appender, parameterized on T, it should work for T,
regardless of what T is doing, and *certainly* regardless of what
fields in T are marked const. Especially considering that if a
field is not marked as const, that hardly means it's not going to
lead to bugs if its memory is reused while you're referencing it!