@nogc and Phobos
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...
Re: @nogc and Phobos
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. :)
Re: @nogc and Phobos
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. :)
Re: @nogc and Phobos
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.
Re: @nogc and Phobos
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? :)
Re: #define-like behavior
Just out of curiosity: Can you explain to me why this is called an `enum` although it's clearly not an enumeration? Seems like a random abuse of a keyword...
Re: #define-like behavior
On Wednesday, 15 March 2023 at 19:27:19 UTC, Paul Backus wrote: It's shorthand for defining an unnamed `enum` with a single member: ... Ah, I see. Thanks!
alias Error: need 'this'
Hi, I read about aliases today and thought it would be handy for shortening repeated access to struct members. However, I'm clearly missing something. Here's some example code: ``` int variableWithALongName = 42; alias alias1 = variableWithALongName; alias1 = 43; assert(variableWithALongName == 43); struct MyStruct { int memberWithALongName; } MyStruct myStruct; myStruct.memberWithALongName = 42; alias alias2 = myStruct.memberWithALongName; alias2 = 43; // does not compile, see below assert(myStruct.memberWithALongName == 43); ``` It works fine with the `int` variable, but with the struct member I get a compilation error: ``` Error: need `this` for `memberWithALongName` of type `int` ``` What is that supposed to mean? Thanks bomat
Re: alias Error: need 'this'
On Sunday, 19 March 2023 at 12:29:19 UTC, Salih Dincer wrote: It is possible to achieve the convenience you want to achieve in 2 ways. One of them is to use a static member but if not, to use an alias inside the container. Thanks for the suggested workaround, I can live with the `static` solution, I guess. I still don't understand why it's necessary, though. Since a `struct` is a value type and, as I understand it, stack allocated, what difference does it make to the compiler whether I alias `variableWithALongName` or `myStruct.memberWithALongName`? Shouldn't it be the exact same underlying mechanism? Thanks and regards bomat
vibe-d REST API: POSTing a struct
Hey everyone, I'm looking into vibe-d, particularly how to build a REST API server. Given this struct: ``` struct Project { string project_id; string name; } ``` I could write a GETter like this: ``` @path("projects/:project_id") Project getProject(string _project_id); ``` and a POST could look like this: ``` Project postProjects(string project_id, string name); ``` So far so good, this works. What I don't like about the POST, though, is that I have to repeat `struct Project`'s members in the parameter list. This is redundant and will be inconvenient every time the struct changes, especially on ones with many members. What I would prefer to have is something like this: ``` Project postProjects(Project project); ``` This is possible, the problem is that the POST request body now must look like this ``` { project: { "project_id": "dummy_id", "name": "dummy" } } ``` rather than simply this ``` { "project_id": "dummy_id", "name": "dummy" } ``` So my question is, is it possible to have vibe-d parse the request body into a struct "implicitly"? I hope the explanation was understandable. :) Any help would be much appreciated. Cheers, bomat
Re: struct initializer
I completely agree with the OP, and I want to illustrate this by another example which I find quite bizarre: ``` struct S { int a; int b; } S[] s_list = new S[0]; // this works S s = { a:1, b:2 }; s_list ~= s; // this does not s_list ~= { a:1, b:2 }; ``` I'm a C++ programmer in my day job and the very first instinct I'd have is to replace the first version by the second to reduce verbosity and eliminate an unnecessary copy. However, for some reason the compiler is not able to deduce the type in the second case, so I'm out of luck. I'm glad to hear that, with a compiler update, I will at least be able to do ``` s_list ~= S( a:1, b:2 ); ``` instead of ``` s_list ~= S( 1, 2 ); ``` but it still seems very inconsistent.
Re: vibe-d REST API: POSTing a struct
On Friday, 1 December 2023 at 19:18:19 UTC, bomat wrote: So my question is, is it possible to have vibe-d parse the request body into a struct "implicitly"? I'm gonna answer my own question here, it's `@bodyParam`. https://forum.rejectedsoftware.com/groups/rejectedsoftware.vibed/thread/40001/ https://github.com/vibe-d/vibe.d/pull/1676 I wasn't aware of the dedicated vibe-d forum before. As I've seen some vibe-d related questions in this forum as well, I thought this would be the place to ask...
Re: vibe-d REST API: POSTing a struct
On Friday, 15 December 2023 at 07:36:04 UTC, aj_dlang wrote: does it active? If you mean if that vibe-d forum is still active, I don't know. I tried to register, but I never got a confirmation mail... so probably not. On the other hand, there wasn't a response to my question on this board either, so don't really know what's the best place to get vibe-d support...
Re: D is nice whats really wrong with gc??
On Monday, 18 December 2023 at 16:44:11 UTC, Bkoie wrote: but what is with these ppl and the gc? [...] I'm a C++ programmer in my day job. Personally, I have no problem with a GC, but one of my colleague is a total C fanboy, so I feel qualified to answer your question. :) I think the problem most "old school" programmers have with automatic garbage collection, or *any* kind of "managed" code, really, is not the GC itself, but that it demonstrates a wrong mindset. If you use (or even feel tempted to use) a GC, it means that you don't care about your memory. Neither about its layout nor its size, nor when chunks of it are allocated or deallocated, etc. And if you don't care about these things, you should not call yourself a programmer. You are the reason why modern software sucks and everything gets slower and slower despite the processors getting faster and faster. In fact, you probably should get another job, like flooring inspector or something. :) And although this is not my opinion (otherwise I wouldn't use D), I have to admit that this isn't completely wrong. I like my abstractions because they make my life easier, but yeah, they detach me from the hardware, which often means things are not quite as fast as they could possibly be. It's a tradeoff. Of course, people with a "purer" mindset could always use the "BetterC" subset of D... but then again, why should they? C is perfect, right? :)
Re: D is nice whats really wrong with gc??
On Friday, 22 December 2023 at 16:51:11 UTC, bachmeier wrote: Given how fast computers are today, the folks that focus on memory and optimizing for performance might want to apply for jobs as flooring inspectors, because they're often solving problems from the 1990s. *Generally* speaking, I disagree. Think of the case of GTA V where several *minutes* of loading time were burned just because they botched the implementation of a JSON parser. Of course, this was unrelated to memory management. But it goes to show that today's hardware being super fast doesn't absolve you from knowing what you're doing... or at least question your implementation once you notice that it's slow. But that is true for any language, obviously. I think there is a big danger of people programming in C/C++ and thinking that it *must* be performing well just because it's C/C++. The C++ codebase I have to maintain in my day job is a really bad example for that as well. I say this as I'm in the midst of porting C code to D. The biggest change by far is deleting line after line of manual memory management. Changing anything in that codebase would be miserable. I actually hate C with a passion. I have to be fair though: What you describe doesn't sound like a problem of the codebase being C, but the codebase being crap. :) If you have to delete "line after line" of manual memory management, I assume you're dealing with micro-allocations on the heap - which are performance poison in any language. A decent system would allocate memory in larger blocks and manage access to it via handles. That way you never do micro-allocations and never have ownership problems. Essentially, it's still a "memory manager" that owns all the memory, the only difference being that it's self-written. Porting a codebase like that would actually be very easy because all the mallocs would be very localized. Of course, this directly leads to the favorite argument of C defenders, which I absolutely hate: "Why, it's not a problem if you're doing it *right*." By this logic, you have to do all these terrible mistakes while learning your terrible language, and then you'll be a good programmer and can actually be trusted with writing production software - after like, what, 20 years of shooting yourself in the foot and learning everything the hard way? :) And even then, the slightest slipup will give you dramatic vulnerabilities. Such a great concept.
Re: D is nice whats really wrong with gc??
On Friday, 22 December 2023 at 22:33:35 UTC, H. S. Teoh wrote: IMNSHO, if I had very large data files to load, I wouldn't use JSON. Precompile the data into a more compact binary form that's already ready to use, and just mmap() it at runtime. I wondered about that decision as well, especially because this was internal game data that did not have to be user readable. That's beside the point though; it was a ~10 MB JSON file that took them several minutes to parse. That's really just insane. Turns out it helps if you don't count the length of the entire document for every single value. It also helps if you don't iterate over your entire array of already written values every time you want to insert a new one. :) In case you didn't know the story, here's a link: https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/ I think there are several great lessons in there. Rockstar must have noticed how slow the loading is, but apparently just accepted it as a given... for 7+ years. Who needs optimizations on today's great hardware, right? There couldn't possibly be algorithmic problems in something simple like a JSON parser, right? Second, look at what people suspected as the root cause of the problem, like the P2P architecture. It's funny how speculations about performance problems are *always* wrong. Only measuring will tell you the truth.
Re: Socket handle leak and active handle warning with Vibe-D
I am still getting this in 2024 and vibe.d 0.9.7: ``` Warning: 1 socket handles leaked at driver shutdown. ``` I was wondering if maybe someone has new info on this...
Re: Socket handle leak and active handle warning with Vibe-D
On Sunday, 14 January 2024 at 20:36:44 UTC, Steven Schveighoffer wrote: There should be a version you can enable that tells you where that socket handle was allocated. That might give you a further clue as to why it's not closed when the system shuts down. I think the program tells you which version to enable when this happens, but if not, let me know and I'll find it. -Steve Thanks for the response, Steve. Hmmm, not sure if I'm missing something, but this is all the output I get from the program: ``` [main() INF] Listening for requests on http://[::1]:8080/ [main() INF] Listening for requests on http://127.0.0.1:8080/ [() INF] Received signal 2. Shutting down. [main() INF] Stopped to listen for HTTP requests on ::1:8080 [main( ) INF] Stopped to listen for HTTP requests on 127.0.0.1:8080 Warning: 1 socket handles leaked at driver shutdown. Warning: 1 socket handles leaked at driver shutdown. ``` Unless there's some switch to make it more verbose?
Re: Socket handle leak and active handle warning with Vibe-D
On Monday, 15 January 2024 at 17:45:16 UTC, Steven Schveighoffer wrote: Which driver are you using? In the posix driver, it should mention (and use) the debug flag `EventCoreLeakTrace`. https://github.com/vibe-d/eventcore/blob/7fa0a15fa541c3fcf65640ee332fd3a09c34730c/source/eventcore/drivers/posix/driver.d#L130 I didn't realize this wasn't across the board... -Steve Sorry, I probably should have mentioned I was on Windows. For testing it under Linux I commented out the call to `connectMongoDB`, since I don't have it installed there - and the warning went away. Interesting, I did not suspect that as the source of the problem at all. :P I'm now looking into how to clean up MongoDB connections properly, but don't see anything besides `cleanupConnections()` (which I'm already calling without any effect). Maybe I need to initialize it differently... I'll experiment a bit.
Re: Socket handle leak and active handle warning with Vibe-D
On Monday, 15 January 2024 at 22:19:56 UTC, Steven Schveighoffer wrote: You may have to do the same thing I did with redis: https://github.com/vibe-d/vibe.d/pull/2372 Good luck! I would also say, I don't know why Windows doesn't do the same trace info debug thing, except that probably whomever added it didn't care about windows. Many thanks for the assistance.
Re: Understanding the Use of Nested Import and Selective Import in D
Wow, that was... exhaustive. Thanks for that. :) One more question that I have, though... On Tuesday, 16 January 2024 at 19:05:43 UTC, Jonathan M Davis wrote: The downside of course is that you then have import statements throughout your code, and they're often going to be duplicated throughout a module (or even within a function if you localize them far enough), because separate parts of the code then need their own local imports. Apart from the aesthetic "clutter" of duplicate imports, will they also put additional strain on the compiler and/or affect the resulting binary? I mean, will the imports actually be compiled in several times?