www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - nogc and Phobos

reply bomat <Tempest_spam gmx.de> writes:
Hi all,

I am a C++ programmer in my "day job" and was playing around with 
D to maybe use it in a personal project.

I'm using Dear ImGui for the graphical user interface, for which 
I use this port:
https://github.com/KytoDragon/imgui/

It works fairly well so far, just one problem: Dear ImGui is 
obviously ` nogc`, and I noticed that it doesn't mix with 
standard library functions.
I tried `std.process.executeShell()` (which I'd kinda need for my 
project unless I want do do OS specific API calls), and 
`std.stdio.writeln()` (which I won't exactly be needing, just as 
a very basic test).

So my question is:
Is Phobos essentially incompatible to ` nogc`?
Or is there a trick for mixing GC code with non-GC code that I 
don't know?

I'm assuming the second, for if the first was true I'd say that D 
would be pretty much useless when combined with non-D libs...
Mar 11 2023
next sibling parent reply rempas <rempas tutanota.com> writes:
On Saturday, 11 March 2023 at 12:04:25 UTC, bomat wrote:

Hello! First of all, let's start by making clear of what ` nogc` 
means. It it an attribute that is used one function signatures 
and it annotates that the garbage collector will not be used 
inside this function. However, in the scenario that we have 
`func1` that is annotated with ` nogc` and `func2` that is called 
by `func1`, I don't know if `func2` needs to be annotated with 
` nogc` as well. This is not been said inside the SPEC (or at 
least, I didn't found it with the quick search I did) so someone 
could confirm or deny this if they know.

 It works fairly well so far, just one problem: Dear ImGui is 
 obviously ` nogc`, and I noticed that it doesn't mix with 
 standard library functions.
Is it what people say "100% ` nogc`" which means that it doesn't use the garbage collector or does it use [betterC](https://dlang.org/spec/betterc.html)?
 So my question is:
 Is Phobos essentially incompatible to ` nogc`?
Look [here](https://dlang.org/spec/function.html#nogc-functions) about the features that cannot be used with ` nogc`. Keep in mind that using ` nogc` in your project, will still have it link with Phobos and D's runtime library. `BetterC` is what disables the garbage collector completely (so no need for ` nogc`) but also doesn't make your binary/library link with D's runtime and Phobos. But if you don't use this mode, you will be able to link with the standard library and use the functions that do not use the garbage collector.
 Or is there a trick for mixing GC code with non-GC code that I 
 don't know?
For what I know, you can combine both methods by using the GC and also mannually allocating memory with libc's "malloc" (or of course your own allocator) but you'll probably have to look into some documentation on how to combine them without any sneaky bugs. However, you will probably not have to do anything "special" to make it work. As I never did it, maybe someone else could help on that one.
 I'm assuming the second, for if the first was true I'd say that 
 D would be pretty much useless when combined with non-D libs...
Even if the first was the case (which again, only things that need the GC will not be able to be used), D is far from been "useless". You can use `betterC` and use C's libraries. Personally, that's what I'm doing anyway. Even if there was no garbage collector and a runtime, I still don't like Phobos and the built-in structures of D. It is still far far better than pretty much any other (compiled) language out there in case of usability so it's not useless at all even if you cannot use the standard library!
Mar 11 2023
parent reply bomat <Tempest_spam gmx.de> writes:
On Saturday, 11 March 2023 at 13:18:13 UTC, rempas wrote:
 Even if the first was the case (which again, only things that 
 need the GC will not be able to be used), D is far from been 
 "useless". You can use `betterC` and use C's libraries. 
 Personally, that's what I'm doing anyway. Even if there was no 
 garbage collector and a runtime, I still don't like Phobos and 
 the built-in structures of D. It is still far far better than 
 pretty much any other (compiled) language out there in case of 
 usability so it's not useless at all even if you cannot use the 
 standard library!
Hi rempas, just wanted to answer to this one separately for two reasons, first: I didn't want to sound aggressive or like I was trying to bash D, sorry if it came across like that. Second: I find it super interesting what you say about you not actually liking Phobos and the built-in structures of D. Although I have not seen very much yet, I think I have to agree to that. Although I come from a C++ background, I'm not exactly a fanboy of that language (you can probably tell, otherwise I wouldn't be here). But after hearing praise for D for being a cleaner and better version of C/C++, I am a bit disappointed so far, tbh. I don't want to go into too much detail here to not derail the thread entirely, but I think it repeats too many old sins, like implicit type conversions, the `for` loop syntax (although I guess one wouldn't need it that often because of `foreach`), the `switch` `case` fallthrough, and the cancerous `const` (as far as I can tell, `immutable` is an even worse flavor of it). Despite all of that, I can't argue with the fact that it may still be the best compiled language currently around. Sadly enough, though, imo that isn't that much of a compliment. :)
Mar 11 2023
next sibling parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Sat, Mar 11, 2023 at 04:21:40PM +0000, bomat via Digitalmars-d-learn wrote:
[...]
 Although I come from a C++ background, I'm not exactly a fanboy of
 that language (you can probably tell, otherwise I wouldn't be here).
 But after hearing praise for D for being a cleaner and better version
 of C/C++, I am a bit disappointed so far, tbh. I don't want to go into
 too much detail here to not derail the thread entirely, but I think it
 repeats too many old sins, like implicit type conversions, the `for`
 loop syntax (although I guess one wouldn't need it that often because
 of `foreach`), the `switch` `case` fallthrough, and the cancerous
 `const` (as far as I can tell, `immutable` is an even worse flavor of
 it).
[...] I also came from a C/C++ background. The GC turned me off D for a long time, until one day I decided to just give it a try to see if it was all as bad as people made it sound. I have to admit that GC phobia stuck with me for a long time, but once I actually started using the language seriously, I discovered to my surprise that it wasn't *that* big of a deal as I had thought. In fact, I found that I quite liked it, because it made my APIs cleaner. A LOT cleaner because I didn't have to pollute every function call with memory management paraphrenalia; they can be nice and clean with no extraneous detritus and things Just Work(tm). Also, the amount of time/effort spent (i.e., wasted) debugging memory problems was gone, and I was a LOT more productive than I ever was in C++. True, I have to relinquish 100% control of my memory, and as an ex-C++ fanboy I totally understand that it's not a pleasant feeling. But I have to say that I was pleasantly surprised at how much D's GC *didn't* get in my way, once I actually started using it for real (toy examples can be misleading). Why am I saying all this? Because to be frank, you haven't really used D if you've been avoiding its standard library like the plague. Not all of Phobos is GC-dependent; the range-based stuff, for example, lets you avoid GC use most of the time. True, for exceptions you need GC, but exceptions are supposed to be ... exceptions ... not the norm, and in practice it isn't really *that* big of a deal. You shouldn't be catching exceptions inside performance-sensitive inner loops anyway. D's strong points don't really show until you start using range-based stuff with UFCS chains -- now *that's* power. Even if you dislike the GC you can still mostly manage your own memory, and let the GC be the fallback mechanism for stuff you missed. As for implicit type conversions: I don't know where you got your information from, but D's implicit conversions are a WHOLE different world from C++. Walter has resisted adding implicit conversion mechanisms in spite of harsh criticism and constant pressure, and in practice, you aren't gonna see a lot of it in D code, if at all. It's not even close to C++ where SFINAE + Koenig lookup gang up on you from behind and you don't even know what hit you. Issues with implicit conversions in D only really come up if you go out of your way to abuse alias this and/or use short ints a little too zealously. Otherwise in practice it's not even an issue IME. For-loop syntax: I can't remember the last time I wrote one in D. Maybe I did like 1 or 2 times (across my 20+ D projects) when I really needed to do something weird with my loops. But foreach covers 90% of my looping needs, and while loops take care of the 9.9% of the cases. Besides, once you start getting used to UFCS chains and Phobos algorithms, most of the time you won't even be writing any loops at all. You won't believe how much more readable your code becomes when you can finally stop worrying about pesky fragile loop conditions and just tack on a couple more components to your UFCS chain and it just automagically takes care of itself. Again, not something you'll understand if you never tried to use D in a serious way. I recommend actually trying to write D, not as transplanted C++, but the way D code is meant to be written. As for switch: yeah D switch has some crazy parts (like Duff's device -- you can actually write that in D). But I've never needed to use it... also, final switch + enums = awesome. As for const: I hardly ever use it. It's useful occasional for low-level code, but not much beyond that. My advice: don't bother. Just pretend it doesn't exist, and your life will be happier. Well OK, once in a while you do need to deal with it. But if it were me, I'd avoid it unless I have to. It doesn't mix well with high-level code, I'll put it that way. Immutable is the same thing, I only use it as `static immutable` just so the compiler would put my data in the preinitialized segment. Other than that, I don't bother. T -- If you're not part of the solution, you're part of the precipitate.
Mar 11 2023
parent bomat <Tempest_spam gmx.de> writes:
Thanks a lot for taking the time and replying in that much detail!

On Saturday, 11 March 2023 at 21:07:18 UTC, H. S. Teoh wrote:
 I also came from a C/C++ background.  The GC turned me off D 
 for a long time, until one day I decided to just give it a try 
 to see if it was all as bad as people made it sound. [...]
That is actually not my issue at all. While I see the benefits of "manual" memory management, these quickly go away when it's done badly, and in my day job I am actually maintaining a project where it is a mess and just using a garbage collected language would have been a much better choice. Because guess what, if you go for manually managing your memory, you actually *have* to do the management properly.
 Why am I saying all this?  Because to be frank, you haven't 
 really used D if you've been avoiding its standard library like 
 the plague.
Again, I'm afraid this is a bit of a misunderstanding. I'm not trying to avoid the standard library, in fact I wanted to use it and thought I couldn't because I'm also using a nogc library. But turns out I was just doing it wrong. :)
 As for implicit type conversions: I don't know where you got 
 your information from, but D's implicit conversions are a WHOLE 
 different world from C++.
I am still a complete noob in D, at this point very little of my information comes from practical experience, but mostly what I've read in "Programming in D" by Ali Cehreli (yeah, I still kinda like books, I'm weird that way). As for the conversion, it might not be as bad as in C++ where it will just silently construct new objects as long as there's a ctor with a matching parameter list somewhere, but it will still implicitly cast an `enum` to its underlying type, or a `bool` to an `int`. Now you may call me too strict about this, or point out that it will never be a problem in any real world use case, but if you take this classic example (which happens to actually be in the book as well, p. 20): `(30 > 20) > 10`, equals `false`. Well at least you have to use the parantheses, which is an improvement I guess, but still, this is something that I hate to see in any language that calls itself type safe. You see, the second language I ever learned was Pascal, and while that has many issues of it's own, it irks me how so many modern languages do things wrong that Pascal did right as early as 1970. And to me, one of those things is that above code *should not even compile*. "True" should not be comparable to 10, because "True" is not a number. And it should not be treated as such just because of how it is stored internally, as this is, after all, just an implementation detail. When you ask someone on the street if "True" plus two was three, he would call you a fool, and so should your compiler.
 Otherwise in practice it's not even an issue IME.
Yeah, probably right. Actually very few people have ever agreed with me on that one. Maybe I'm weird. :)
 For-loop syntax: I can't remember the last time I wrote one in 
 D. Maybe I did like 1 or 2 times (across my 20+ D projects) 
 when I really needed to do something weird with my loops.
As I wrote, I expected as much. So it's not so much a real problem as a general concept that I dislike; even if something is rarely (if ever) used: when you put it into your language, why do it in such a weird and ugly way just to have it look similar to C? I don't get it, is all. But I also didn't get it in JavaScript or any other language that adopted the C syntax, so it's not D specific.
 Again, not something you'll understand if you never tried to 
 use D in a serious way.
Completely true. Again, I'm totally new to D and my criticism is kinda academic. I know that.
 I recommend actually trying to write D, not as transplanted 
 C++, but the way D code is meant to be written.
But this is actually my point. Since D is *not* C++, it should not have adapted the `for` or `switch` syntax in almost exactly the same weird way. And saying that I shouldn't bother because I can always choose to not use it just seems like a very bad argument to me, sorry. It's kinda like saying that C++ wasn't a bad language when you just ignore 50% of it, which most people actually do. :)
 As for const: I hardly ever use it. It's useful occasional for 
 low-level code, but not much beyond that.  My advice: don't 
 bother. Just pretend it doesn't exist, and your life will be 
 happier. [...]
Same here. I have no problem with stuff in a language that I don't want to use, after all I guess you'll have that in every language. Still, especially as a beginner, I think it is legitimate to wonder why it was put in. `const` has always gotten a lot of heat by C++ programmers, so what is the reasoning behind putting an even stricter version of it into a language that aspires to be a cleaner and better version of C++? And again, I'm not trying to be the smartass who could have done it better, I'm just trying to understand it. Taking your first steps into a new language, you just stumble across these things. Thanks again for your time!
Mar 14 2023
prev sibling parent reply rempas <rempas tutanota.com> writes:
On Saturday, 11 March 2023 at 16:21:40 UTC, bomat wrote:
 first: I didn't want to sound aggressive or like I was trying 
 to bash D, sorry if it came across like that.
Oh don't worry! People have openly criticized (and still doing) the language before. It's nothing to worry, criticism help us becoming better. But I didn't got these vibes from your post to begin with ;)
 Second: I find it super interesting what you say about you not 
 actually liking Phobos and the built-in structures of D.
 Although I have not seen very much yet, I think I have to agree 
 to that.
Well, when I first started using D, coding on it was very very easy and enjoyable. I didn't had to think a lot and things "just worked"™️. Then, things chanced... Haven't made anything at this point except for some small programs. Now, I'm making my first "big" project and it's a compiler for my new language. So ironically enough, that will be my first and final project in D.
 Although I come from a C++ background, I'm not exactly a fanboy 
 of that language (you can probably tell, otherwise I wouldn't 
 be here).
My dear, if anyone would tell me that they are a fanboy of this mess called C++, I wouldn't believe them...
 But after hearing praise for D for being a cleaner and better 
 version of C/C++, I am a bit disappointed so far, tbh.
Well, of course we are a little bit disappointed when things are not tuned EXACTLY how we want them. There are things that D OBJECTIVELY does just wrong and they could have been much better. However, it's still much much much much better than C and even C++. And that's not a lie and I'm not a "fanboy". I tried to use them both for my project and D is straight up day and night with these two. If D has 3-4 annoying things, C and C++ have 10! And again, this is with `betterC` in mind. I don't even use the whole power of D. But again, nothing is perfect unless you build it, hence why I making my own that will include a lot of great features from D as it also objectively handles some things with a good way.
 but I think it repeats too many old sins, like implicit type 
 conversions, the `for` loop syntax (although I guess one 
 wouldn't need it that often because of `foreach`),
Does it have "implicit" type conversion? I didn't even knew, lol! The `foreach` will cover your needs like you said but ironically enough, I like and use the original `for` loop.
 the `switch` `case` fallthrough,
I have nothing to say for that, I have said it before and lots of others have as well.
 and the cancerous `const` (as far as I can tell, `immutable` is 
 an even worse flavor of it).
Yeah, another thing I'll change in my language. The way immutability is treated is so so bad for so many reasons.
 Despite all of that, I can't argue with the fact that it may 
 still be the best compiled language currently around. Sadly 
 enough, though, imo that isn't that much of a compliment. :)
Well, the competition is pretty weak, yeah. Tho based on my experience, it doesn't worth to waste your time on anything else at this point. We can speak about trying a different language after mine is out ;)
Mar 11 2023
parent reply bomat <Tempest_spam gmx.de> writes:
On Saturday, 11 March 2023 at 22:14:36 UTC, rempas wrote:
 The `foreach` will cover your needs like you said but 
 ironically enough, I like and use the original `for` loop.
Thanks for your reply as well, rempas... I guess I covered most things in my earlier reply, but on the `for` loop: Coming from Basic and then Pascal, when I first saw that atrocity I was like... seriously? I think most people don't see it anymore because they have become so used to it, but the sequence of abort condition and increment steps is completely arbitrary, and commas and semicolons are used like literally *nowhere else* in the language (C and C++ that is, not sure yet about D). It's a marvel of inconsistency. I don't mind it as much today, since I must have written thousands of `for` loops by now and I do it totally automatically. I just don't know how it could become such a success story in so many languages and it *just*. *won't*. *die*. :)
 Well, the competition is pretty weak, yeah. Tho based on my 
 experience, it doesn't worth to waste your time on anything 
 else at this point. We can speak about trying a different 
 language after mine is out ;)
Sounds intriguing. Anything I can look at yet? Or still all top secret? :)
Mar 14 2023
parent rempas <rempas tutanota.com> writes:
On Tuesday, 14 March 2023 at 20:40:39 UTC, bomat wrote:
 Sounds intriguing. Anything I can look at yet? Or still all top 
 secret? :)
Oh, amazing! I let you on waiting for almost a month and I wouldn't had see it if I didn't came to post another question..... I'm so so sorry for the waiting, I will not even use an excuse. So, if you are willing to make an account on [Codeberg](https://codeberg.org/), the repository is private but after making the account, follow [me](https://codeberg.org/rempas) and I will give you access! Tho, you may read something cringe! Be prepared, lol!
Apr 12 2023
prev sibling next sibling parent Mike Parker <aldacron gmail.com> writes:
On Saturday, 11 March 2023 at 12:04:25 UTC, bomat wrote:

 So my question is:
 Is Phobos essentially incompatible to ` nogc`?
 Or is there a trick for mixing GC code with non-GC code that I 
 don't know?

 I'm assuming the second, for if the first was true I'd say that 
 D would be pretty much useless when combined with non-D libs...
Any function annotated with ` nogc` can only call other ` nogc` functions, but they can be called by *any* function. So it won't affect your use of the GC or Phobos in that regard. Or is there a specific problem you've encountered?
Mar 11 2023
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 3/11/23 7:04 AM, bomat wrote:
 Hi all,
 
 I am a C++ programmer in my "day job" and was playing around with D to 
 maybe use it in a personal project.
 
 I'm using Dear ImGui for the graphical user interface, for which I use 
 this port:
 https://github.com/KytoDragon/imgui/
 
 It works fairly well so far, just one problem: Dear ImGui is obviously 
 ` nogc`, and I noticed that it doesn't mix with standard library functions.
 I tried `std.process.executeShell()` (which I'd kinda need for my 
 project unless I want do do OS specific API calls), and 
 `std.stdio.writeln()` (which I won't exactly be needing, just as a very 
 basic test).
 
 So my question is:
 Is Phobos essentially incompatible to ` nogc`?
 Or is there a trick for mixing GC code with non-GC code that I don't know?
Most of Phobos uses exceptions, which require the gc.
 
 I'm assuming the second, for if the first was true I'd say that D would 
 be pretty much useless when combined with non-D libs...
I think it is an error to mark a library which centers on callbacks with always being nogc. You can work around nothrow and safe, but not nogc. This also brings up a point that there just isn't a way to do a callback-centered library that can be simultaneously used with nogc or gc, unless you template based on that. It's not a good situation, and I don't know of a good solution. -Steve
Mar 11 2023
parent bomat <Tempest_spam gmx.de> writes:
Thanks for the responses everyone, that was all very helpful and 
got me on the right track.
Especially this:

On Saturday, 11 March 2023 at 14:41:01 UTC, Steven Schveighoffer 
wrote:
 I think it is an error to mark a library which centers on 
 callbacks with always being  nogc. You can work around nothrow 
 and  safe, but not  nogc.
Turns out it was my fault. I was working off example code that came with d-imgui, and the original author took the (rather lazy) approach of wrapping the entire main loop into `nothrow nogc:` I just got rid of that and only marked the callbacks accordingly. Now I can just set status data in the callbacks, then handle it in the main loop. Sorry, still kinda finding my feet here. :)
Mar 11 2023