April 28, 2017
On Thursday, 27 April 2017 at 17:31:42 UTC, bachmeier wrote:
> On Thursday, 27 April 2017 at 15:50:56 UTC, Ben wrote:
>> A few days ago i was reading this topic:
>>
>> https://news.ycombinator.com/item?id=14165198
>>
>> And the whole GC keeps coming up as a negative ( compared to Rust ).
>>
>> From my understanding there has been a proposal DIP1000 to address this issue. Is there any update on this topic?
>>
>> Is it possible to run D without the GC AND the standard library?
>
> There is opposition to the GC from a small but vocal group of mostly C++ developers. Sometimes they even make valid arguments. You can find many threads on the topic here.

Citation needed.
April 28, 2017
On Thursday, 27 April 2017 at 22:43:56 UTC, Moritz Maxeiner wrote:
> You replied to the wrong person here, seeing as I did not link to the article you're referring to,

Sorry...

> so I'll reply:
> Expanding the continuous memory region a dynamic array consists of (possibly moving it) once it overflows has absolutely nothing to do with the GC, or even the language, it's how the abstract data type "dynamic array" is defined. D just does this transparently for you by default. If you already know the exact or maximum size, you can allocate *once* (not 6 times) using `new` and `.reserve` respectively *before* entering the loop, like that article explains in depth.

You seem to be missing the fact that i pointed this out. The fact that the GC might have done up to 6 collection rounds in that loop is "ludicrous".

>
> Um, what? Memory (de)allocation (in C often malloc/free) and object (de)contruction (in C usually functions with some naming conventions like `type_init`/`type_deinit`) are on two entirely different layers! Granted, they are often combined in C to functions with names like `type_new`/`type_free`, but they are conceptually two distinct things. Just to be very clear, here is a primitive diagram of how things work:
> make object O of type T:
> <OS> --(allocate N bytes)--> [memory chunk M] --(call constructor T(args) on M)--> [O]
> dispose of O:
> [O] --(call destructor ~T() on O)--> [memory chunk M] --(deallocate M)--> <OS>
>
> D's garbage collector conceptually changes this to:
> make object O of type T:
> <OS> --(GC allocates)--> [GC memory pool] --(allocate N bytes)--> [memory chunk M] --(call constructor T(args) on M)--> [O]
> dispose of O:
> [O] --(call destructor ~T() on O)--> [memory chunk M] --(deallocate M)--> [GC memory pool] --(GC deallocates)--> <OS>
> with the specific restriction that you have *no* control over 'GC deallocates' and only indirect control over 'GC allocates' (by allocating more memory from the GC than is available its the pool).
>
> Working on the memory chunk layer is memory management.
> Working on the object layer is object lifetime management.
> D offers you both automatic memory management and automatic lifetime management via its GC.
> What you describe is manual object lifetime management (which is what std.conv.emplace and object.destroy exist for) and has no effect on the automatic memory management the GC performs.
> You *can* do manual memory management *on top* of the GC's memory pool (using core.memory.GC.{alloc/free) or the newer, generic Alloactor interface via std.experimental.allocator.gc_allocator.GCAllocator.{allocate/deallocate}), but these operations will (generally) not yield any observable difference from the OS's perspective.
>
>>
>> That is assuming the GC removes the memory reference when you call it. I remember seeing in some other languages ( C# possibly? ) that referring a variable to be freed only meant the GC freed the memory when it felt like it, not the exact spot when you told it.
>
> Again, you seem to mix object lifetime management and memory management. You cannot tell the GC to free memory back to the operating system (which is what the free syscall does and what you seem to be describing). You can *only* free memory you allocated *from* the GC *back* to the GC. The GC decides when (and if) any memory is ever being freed back to the OS (which is kinda one major point of having a GC in the first place).

I know, i do not express myself very well in English.

> In my experience most people's aversion to GCs can be aptly described by the German proverb "Was der Bauer nicht kennt, das frisst er nicht" (the meaning of which being that most people generally like living in comfort zones and rarely - if ever - dare to leave them of their own free will; that includes developers, sadly).

Unfortunately i do have plenty of experience with GC kicking in on the wrong moments ( or not at the right moments, people forget that one ).

I am sure that the amount of people who develop in GC languages is much bigger these days then manual managed languages ( what is more or less a rarity these days among the new languages ). Even Rust still has some background management going on ( like the byte counter ).

Maybe its my opinion only but a good language will not put anything in the way of the developer but will point out mistakes.

The Rust compiler is not a bad example but it can be taken a step more. Is it so hard for developers when you declare a variable, to later also clean it up???

var x = 1;
// Do work
x.free;

Easy ... Sure, it becomes a little bit more tricky with ownership but that is where the compiler can help and simply state: "Hey, you forgot this variable, it does not seem to be used beyond this point". Just calling the x.free seem to be too much work for developers these days.

Up to now i found very few languages that did this correctly. But this is a offtopic discussion.
April 28, 2017
On Friday, 28 April 2017 at 07:35:00 UTC, Ben wrote:

>> so I'll reply:
>> Expanding the continuous memory region a dynamic array consists of (possibly moving it) once it overflows has absolutely nothing to do with the GC, or even the language, it's how the abstract data type "dynamic array" is defined. D just does this transparently for you by default. If you already know the exact or maximum size, you can allocate *once* (not 6 times) using `new` and `.reserve` respectively *before* entering the loop, like that article explains in depth.
>
> You seem to be missing the fact that i pointed this out. The fact that the GC might have done up to 6 collection rounds in that loop is "ludicrous".

How is it ludicrous? The fact that you know the GC will only run during an allocation, and only if it needs to, allows you to control when those opportunities to collect arise. That's a much more palatable situation than if it were sitting in the background, constantly checking if it needs to collect, then doing so without any input from you. There, you'd have no control at all.

In the context of an actual program, the example would only have made 6 collections if you were putting putting heavy pressure on the GC heap, which is an extremely naive way of programming for anyone concerned about performance. D allows you several options to relieve that pressure and assert some control over when the GC can run. Even in a non-GC language, you wouldn't be allocating like that in a performance-critical loop -- you would preallocate before you entered the loop.


April 28, 2017
On Friday, 28 April 2017 at 04:24:43 UTC, Ola Fosheim Grostad wrote:
> On Thursday, 27 April 2017 at 22:43:56 UTC, Moritz Maxeiner wrote:
>> Working on the memory chunk layer is memory management.
>> Working on the object layer is object lifetime management.
>> D offers you both automatic memory management and automatic lifetime management via its GC.
>
> D offers sound automatic lifetime management? Since when?

Why are you implicitly adding adjectives to my sentence that change its meaning?
April 28, 2017
On Friday, 28 April 2017 at 08:25:01 UTC, Moritz Maxeiner wrote:
> On Friday, 28 April 2017 at 04:24:43 UTC, Ola Fosheim Grostad wrote:
>> On Thursday, 27 April 2017 at 22:43:56 UTC, Moritz Maxeiner wrote:
>>> Working on the memory chunk layer is memory management.
>>> Working on the object layer is object lifetime management.
>>> D offers you both automatic memory management and automatic lifetime management via its GC.
>>
>> D offers sound automatic lifetime management? Since when?
>
> Why are you implicitly adding adjectives to my sentence that change its meaning?

If it isn't sound then it isn't worth mentioning...

April 28, 2017
On Friday, 28 April 2017 at 07:35:00 UTC, Ben wrote:
> On Thursday, 27 April 2017 at 22:43:56 UTC, Moritz Maxeiner wrote:
>> D just does this transparently for you by default. If you already know the exact or maximum size, you can allocate *once* (not 6 times) using `new` and `.reserve` respectively *before* entering the loop, like that article explains in depth.
>
> You seem to be missing the fact that i pointed this out. The fact that the GC might have done up to 6 collection rounds in that loop is "ludicrous".

You wrote:
> I if did my own memory management, the variable cleanup will have been done in one go, right after the loop. Simply more efficient.

You wrote about cleaning up *after* the loop, *not* about allocating *before* the loop. They are semantically related (as allocating with the GC *might* kick off a collection cycle), but not the same thing.

>
>> In my experience most people's aversion to GCs can be aptly described by the German proverb "Was der Bauer nicht kennt, das frisst er nicht" (the meaning of which being that most people generally like living in comfort zones and rarely - if ever - dare to leave them of their own free will; that includes developers, sadly).
>
> Unfortunately i do have plenty of experience with GC kicking in on the wrong moments ( or not at the right moments, people forget that one ).

In which language(s)? Because in D it's both easy and simple to avoid that (Use @nogc or compile with `-vgc` and inspect).

>
> Maybe its my opinion only but a good language will not put anything in the way of the developer but will point out mistakes.

Safety properties may be what you're looking for. See @safe, that's an area of D a lot of work is currently being done on.

>
> The Rust compiler is not a bad example but it can be taken a step more. Is it so hard for developers when you declare a variable, to later also clean it up???
>
> var x = 1;
> // Do work
> x.free;

If you write it like that, yes, because often it's not just one such make/dispose pair per scope, but multiple, possibly overlapping ones and people make mistakes. And the more complex a piece of code gets the harder it becomes to decipher such pairs and/or decide if the "closing" dispose is missing.
This is one of the reasons why scope guards are good:

var x = 1;
scope (exit) x.free
// Do work

This, as code becomes more complex, allows for much easier reading (and understanding) of lifetimes.


>
> Easy ... Sure, it becomes a little bit more tricky with ownership but that is where the compiler can help and simply state: "Hey, you forgot this variable, it does not seem to be used beyond this point".

Since the GC is memory safe by definition (sans bugs) you'd only need this for where you aren't using it. And for the rest I'm not sure it can be done sanely: How's the compiler to know, e.g., which functions from a C API (or C++) you call into allocate or deallocate memory? Introduce yet another keyword or @property to signal cross-language memory management? If you ignore cross-language calls and only remain within D, I suppose it might be viable to write a semantic pass for it, but from my perspective, the cross-language calls are the *much* bigger threat to memory safety.

> Just calling the x.free seem to be too much work for developers these days.

In my experience reading about such occurences, this usually happens when the lifetime of the object the memory is used for has become unclear.

>
> Up to now i found very few languages that did this correctly.

I don't share your assessment of what's correct, but yes, we digress.


April 28, 2017
On Friday, 28 April 2017 at 08:26:28 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 28 April 2017 at 08:25:01 UTC, Moritz Maxeiner wrote:
>> On Friday, 28 April 2017 at 04:24:43 UTC, Ola Fosheim Grostad wrote:
>>> On Thursday, 27 April 2017 at 22:43:56 UTC, Moritz Maxeiner wrote:
>>>> Working on the memory chunk layer is memory management.
>>>> Working on the object layer is object lifetime management.
>>>> D offers you both automatic memory management and automatic lifetime management via its GC.
>>>
>>> D offers sound automatic lifetime management? Since when?
>>
>> Why are you implicitly adding adjectives to my sentence that change its meaning?
>
> If it isn't sound then it isn't worth mentioning...

So you claim...
April 28, 2017
On Friday, 28 April 2017 at 09:02:19 UTC, Moritz Maxeiner wrote:
> On Friday, 28 April 2017 at 08:26:28 UTC, Ola Fosheim Grøstad wrote:
>> If it isn't sound then it isn't worth mentioning...
>
> So you claim...

Actually, unsound lifetime management is worse than nothing as far as correctness goes... so I guess it is worth mentioning as a warning rather than a recommendation.

If D had ownership pointers then it would've been possible to sort this out, but D is perpetually locked to the current pointer/GC model for reasons that aren't particularly convincing, i.e. beliefs.


April 28, 2017
On Friday, 28 April 2017 at 09:12:03 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 28 April 2017 at 09:02:19 UTC, Moritz Maxeiner wrote:
>> On Friday, 28 April 2017 at 08:26:28 UTC, Ola Fosheim Grøstad wrote:
>>> If it isn't sound then it isn't worth mentioning...
>>
>> So you claim...
>
> Actually, unsound lifetime management is worse than nothing as far as correctness goes... so I guess it is worth mentioning as a warning rather than a recommendation.

Actually, applying "sound" or "unsound" to D's GC lifetime management in general is worse than realizing that whether using it for a specific use case is sound or unsound is entirely dependent on that use case... so I guess it is worth mentioning as a tool a developer should read up on.
Also, you seem to imply that I made a recommendation to use the GC's lifetime management. I did not.


>
> If D had ownership pointers then it would've been possible to sort this out, but D is perpetually locked to the current pointer/GC model for reasons that aren't particularly convincing, i.e. beliefs.

I'm sorry, but that's just plain wrong. D does not have ownership pointers because nobody that wants them has stepped up and
1) Done the work of drafting an informal proposal that *actually deals with _all_ of the issues involved*
2) Developed that informal proposal into a DIP
3) Wrote the implementation and sent a PR
Every time it comes up there are ideas, or sometimes even reasonably well formed informal proposals, but none of the proponents ever actually follows up and improves such proposals to the point where all the issues are dealt with. Claiming that D doesn't have ownership mechanics because of beliefs when none of the (vocal) proponents are willing to actually get down to it and *do the work* is, frankly, asinine; do you generally expect people to do things for you they aren't interested in without recompense?
April 28, 2017
On Friday, 28 April 2017 at 09:40:07 UTC, Moritz Maxeiner wrote:
> I'm sorry, but that's just plain wrong. D does not have ownership pointers because nobody that wants them has stepped up and
> 1) Done the work of drafting an informal proposal that *actually deals with _all_ of the issues involved*

Wrong. This has been discussed and hashed out to death over and over again. The solutions are on the table.

Walter's position has always been that having more than a single pointer type is a disaster.

That makes further work on it pointless.

(Although, arguably, D kinda has several pointer types already).