Re: Program crash: GC destroys an object unexpectedly
On 9/14/21 7:31 AM, eugene wrote: On Monday, 13 September 2021 at 17:18:30 UTC, eugene wrote: Then after pressing ^C (SIGINT) the program gets SIGSEGV, since references to sg0 and sg1 are no longer valid (they are "sitting" in epoll_event structure). ... forget to mention, crashes here: ```d bool wait() { const int maxEvents = 8; EpollEvent[maxEvents] events; if (done) return false; int n = epoll_wait(id, events.ptr, maxEvents, -1); if (-1 == n) return false; foreach (k; 0 .. n) { EventSource s = events[k].es; ulong ecode = s.eventCode(events[k].event_mask); // < SIGSEGV ``` sg0/sg1 are destroyed, so s points to wrong location. Note that s likely still points at a valid memory address. However, when an object is destroyed, its vtable is nulled out (precisely to cause a segfault if you try to use an already-freed object). There is also the possibility the memory block has been reallocated to something else, and that is causing the segfault. But if the segfault is consistent, most likely it's the former problem. -Steve
Re: Program crash: GC destroys an object unexpectedly
On 9/14/21 1:49 AM, Tejas wrote: On Monday, 13 September 2021 at 18:42:47 UTC, Steven Schveighoffer wrote: On 9/13/21 1:54 PM, eugene wrote: [...] The GC only scans things that it knows about. Inside your EventQueue you have this code: [...] Umm is it okay that he declared variables `init` and `idle` of type `Stage` inside the constructor? Maybe that has something to do with this? Also, calling a variable `init` could be problematic since the compiler assigns a property of the same name to every single type? Declaring a member/field named `init` is likely a bad idea, but this is not a member, it's just a variable. That's fine. `idle` doesn't mean anything special to D. This project is too big and complex for me to diagnose by just reading, it would take some effort, and I don't have the time, sorry. Though as I have learned helping C converts before, most of the time things like this have to do with forgetting to store a GC reference somewhere. It can be subtle too... I still recommend pinning the object when adding the epoll event and seeing if that helps. -Steve
Re: Program crash: GC destroys an object unexpectedly
On 9/13/21 1:54 PM, eugene wrote: On Monday, 13 September 2021 at 17:40:41 UTC, user1234 wrote: The problems seems to lies in `newSignal()` which "would" not allocate using the GC. final Signal newSignal(int signum) { Signal sg = new Signal(signum); sg.owner = this; sg.number = sg_number++; sg.register(); return sg; } full src is here http://zed.karelia.ru/0/e/edsm-in-d-2021-09-10.tar.gz The GC only scans things that it knows about. Inside your EventQueue you have this code: ```d void registerEventSource(EventSource es) { auto e = EpollEvent(0, es); int r = epoll_ctl(id, EPOLL_CTL_ADD, es.id, ); assert(r == 0, "epoll_ctl(ADD) failed"); } EventQueue opOpAssign(string op)(EventSource es) if (("+" == op) || ("~" == op)) { registerEventSource(es); return this; } void deregisterEventSource(EventSource es) { auto e = EpollEvent(0, es); int r = epoll_ctl(id, EPOLL_CTL_DEL, es.id, ); assert(r == 0, "epoll_ctl(DEL) failed"); } EventQueue opOpAssign(string op)(EventSource es) if ("-" == op) { deregisterEventSource(es); return this; } ``` And you are registering your signals using the `+=` operator. What is happening here, is, `epoll_ctl` is adding your event source to a *C allocated* structure (namely the epoll struct, allocated by `epoll_create1`, and possibly even managed by the OS). The GC does not have access to this struct, so if that's the only reference to them, they will get cleaned up by the GC. Now, with your stopper code that you showed, it looks like you are storing the reference to stopper right on the main stack frame. This *should* prevent those from being destroyed, since Stopper has a reference to both signals. But I would recommend using `core.memory.GC.addRoot` on your EventSource when registering it with epoll, and using `core.memory.GC.removeRoot` when unregistering. That will ensure they do not get cleaned up before being unregistered. If this doesn't fix the problem, perhaps there is some other issue happening. -Steve
Re: Which operators cannot be overloaded and why not?
On 9/13/21 10:47 AM, user1234 wrote: On Monday, 13 September 2021 at 14:33:03 UTC, user1234 wrote: what else ? when you have ```d alias AA1 = int[int]; alias AA2 = AA1[int]; ``` then you can write ```d AA2 aa; aa[0] = [0 : 0]; aa[0][0] = 0; ``` The `[0][0]` cannot be expressed using operator overloads (and a custom map type that implements opIndexAssign).But this case is rather due to the fact that druntime seems to do something a bit unusal here (according to an old discussion that happend once on irc). This is because the compiler calls a different hook depending on the usage of the expression `aa[0]`. Which one it calls is not consistent. There isn't an analog for indexing overloads. A further example: ```d int[int] aa; aa[0]++; // ok void foo(ref int x) {x++;} foo(aa[1]); // range violation ``` -Steve
Re: Ali's Book - Programming in D
On 9/10/21 10:21 AM, Ali Çehreli wrote: I want to thank Steven Schveighoffer here once more for his help with the book. I later realized that his name should have much more prominence. I can't understand how my older self did not realize this fact when the book was being finalized. Your memory may be quite faulty! I think I did review quite a bit of it, but I think I didn't finish reviewing everything (it is a big book). But thank you! -Steve
Re: GDC - program runs in one thread, DMD - in 4 threads, why?
On 9/10/21 7:47 AM, eugene wrote: On Friday, 10 September 2021 at 11:09:10 UTC, bauss wrote: --DRT-gcopt=parallel:2 on the command line. A value of 0 disables parallel marking completely. but it does not: make -f Makefile-dmd dmd --DRT-gcopt=parallel:0 engine/*.d common-sm/*.d server-sm/*.d pool.d echo_server.d -ofecho-server dmd --DRT-gcopt=parallel:0 engine/*.d common-sm/*.d client-sm/*.d pool.d echo_client.d -ofecho-client ps xH | grep [e]cho 5460 pts/14 Sl+ 0:00 ./echo-server 5460 pts/14 Sl+ 0:00 ./echo-server 5460 pts/14 Sl+ 0:00 ./echo-server 5460 pts/14 Sl+ 0:00 ./echo-server 5466 pts/15 Sl+ 0:00 ./echo-client 5466 pts/15 Sl+ 0:00 ./echo-client 5466 pts/15 Sl+ 0:00 ./echo-client 5466 pts/15 Sl+ 0:00 ./echo-client `--DRT...` is a d runtime switch, which is processed while running your program, not by the compiler. Try `./echo-client --DRT-gcopt=parallel:0` There is also a way to add this to your program so it's not needed on the command line. -Steve
Re: Ali's Book - Programming in D
On 9/10/21 6:46 AM, Ron Tarrant wrote: I guess this is mainly a question for Ali, but if anyone else knows the answer, please jump in... If I were to buy a paperback copy of "Programming in D: Tutorial & Reference" from Amazon (this link: https://www.amazon.ca/Programming-Tutorial-Reference-Ali-Cehreli/dp/1515074609/ref=sr_1_1?dchild=1=programming+in+d%3A+tutorial+and+reference=1631270580=8-1) would I be getting the 2021 edition or an earlier one? If I can't get the latest edition from Amazon, is there a place where I can get it? Thanks. Ali's book is generally "print-on-demand". But I don't know the details of how often it gets re-upped on those sites. I'd suggest you wait for Ali to wake up (he's on west coast of the US), and he likely will respond ;) -Steve
Re: Is std.variant useful for types only known at run time?
On 9/8/21 5:55 AM, Chris Piker wrote: On Wednesday, 8 September 2021 at 08:39:53 UTC, jfondren wrote: so I'd look at a std.sumtype of them first: Wow, this forum is like a CS department with infinite office hours! Interesting. I presume that the big win for using std.sumtype over a class set is value semantics instead of reference semantics? So out of curiosity, say each structure implemented a function to provide the desired broken-down-time, would the following "virtual function" style call work? ```d import std.sumtype; struct BDTime { int y, int m, int d, int h, int m, double s }; struct ISO8601 { BDTime bdTime(){ ... } } struct FloatEpoch { BDTime bdTime(){ ... } } struct DoubleEpoch { BDTime bdTime(){ ... } } struct LongEpoch { BDTime bdTime(){ ... } } alias Time = SumType!(ISO8601, FloatEpoch, DoubleEpoch, LongEpoch); void main() { import std.stdio : writeln; import std.format : format; Time e = ISO8601(); BDTime = e.bdTime(); } ``` or would I need to use `match!` to get the right structure type and then generate the internal time representation? Just as an aside, [taggedalgebraic](https://code.dlang.org/packages/taggedalgebraic) does this for you. -Steve
Re: Forum posting question ... how post a thread question with color syntax highlighting ??
On 9/6/21 10:13 AM, Mike Parker wrote: On Monday, 6 September 2021 at 13:23:21 UTC, Steven Schveighoffer wrote: I will note though, that some people use the mechanism for links that puts the link at the bottom of the post, and this can be annoying when you reply, if you don't include the link definition, it doesn't render correctly. Now that's interesting. I had assumed it would be less annoying than having them inline. Especially since people had already adopted a similar convention before we got Markdown support. I gave up on Thuderbird and went full-on with the web interface a couple of years ago, so I've had no view of the experience post-Markdown. Yeah the convention isn't terrible, but it looks weirder for sure when the link is missing. E.g. look at this post: https://forum.dlang.org/post/miahenxocgxpvasqg...@forum.dlang.org and then a reply: https://forum.dlang.org/post/jreujgbixqadnwjsi...@forum.dlang.org -Steve
Re: Forum posting question ... how post a thread question with color syntax highlighting ??
On 9/5/21 9:18 PM, Ali Çehreli wrote: On 9/5/21 4:24 PM, someone wrote: > > For example; IIRC Ali's posts are always no-markdown. > That's because I've been using Thunderbird for mail and news for a long time now and unfortunately it is impossible to convince Thunderbird to add the necessary header field. (Vladimir has a recommendation where I can run a simply local server that augments Thunderbird's headers but I haven't tried it yet.) I should go back to using Emacs for news. I am pretty sure it will be configurable. Ali This is *exactly* how I do it. Though I have started creating an iopipe-based clone cause I wanted to see if I could do it. Unfortunately std.io is not mature enough. I plan to have a dub project so you can just `dub run thunderbirdmarkdown` and now you have a solution. And to answer someone's question, I think everyone is fine with markdown, they just don't always have the capability. I will note though, that some people use the mechanism for links that puts the link at the bottom of the post, and this can be annoying when you reply, if you don't include the link definition, it doesn't render correctly. -Steve
Re: Forum posting question ... how post a thread question with color syntax highlighting ??
On 9/5/21 2:07 PM, james.p.leblanc wrote: But, my eyes had been looking for the beautiful green and blue text as an example ... So, I completely missed the fact that the "highlight syntax" in the box was exactly what I was looking for. Actually, it may not be a bad idea to make that example markdown more colorful by adding some keywords and comments. Maybe instead of ```d writeln("D is great!"); ``` it could be: ```d // should be highlighted! auto str = "D is great!"; ``` -Steve
Re: Forum posting question ... how post a thread question with color syntax highlighting ??
On 9/5/21 1:48 PM, james.p.leblanc wrote: Dear All, I have noticed that quite a few posts and responses on this forum include d snippets made with **nicely colored syntax highlighting.** (I do not mean just the bold markdown text.) This increases post clarity significantly. How is this being done? (I hope that this is not considered off topic. My goal would be able to make such posts myself. But also, if more post in this manner, it may help many.) The markdown link in the forum UI should tell you how it works. In case you can't find it, the info is [here](https://forum.dlang.org/help#markdown) -Steve
Re: Phobos Unittest
On 9/4/21 4:05 PM, Per Nordlöw wrote: On Saturday, 4 September 2021 at 13:12:49 UTC, Steven Schveighoffer wrote: Note that lexing and parsing is extremely quick, and I wouldn't focus on trying to trim this out, you won't get much performance out of that. -Steve For the record, a D file containing only `import std;` type checks via ```sh time dmd import_std.d -o- ``` in 0.20s whereas ```sh time dmd import_std.d -o- ``` in 0.45s on my ThreadRipper. I doubt that's because of the parsing. I've [gone down](https://github.com/schveiguy/dmd/tree/debugunitteststuff) these kinds of rabbit holes. It's one of the reasons I tried to remove ALL version(unittest) blocks from phobos that import other modules. But you just can't remove them all. And any unittests inside templates are going to compile and get included, even if you don't instantiate anything. I also discovered that CTFE initializers run, even if you don't use the imported symbol, and even if you don't need type inference. Can't remember if that got fixed. I think you would find you could probably attribute the 0.25s there to a few modules that do things when unittests are turned on. According to https://github.com/dlang/dmd/blob/1ae5fee06ddd0599fb187595f8b0cebf8c840ebd/src/dmd/parse.d#L642-L683, if unittests aren't turned on, indeed the parser simplifies its parsing of the unittest. It skips over the unittest block, and doesn't allocate any AST nodes for it. But that difference I don't think is going to be the cause for a significant slowdown. One can construct a test to check the parsing: 1. Generate a huge source file with 10,000 (or maybe more?) non-trivial unittests. You need enough to move the needle on parsing. 2. Import that file, and build the main file with and without the -unittest flag. 3. This should not actually compile the unittests, but just parse them. Using phobos as a test case is rife with things that may be contributing besides the parser. -Steve
Re: Phobos Unittest
On 9/4/21 7:43 AM, Johan wrote: On Saturday, 4 September 2021 at 03:18:01 UTC, Paul Backus wrote: On Saturday, 4 September 2021 at 00:09:37 UTC, H. S. Teoh wrote: This is related to the bogonity of the current behaviour of -unittest, which compiles *all* unittests of *all* imported modules, even when you're compiling user code that has no interest in Phobos unittests. Well, no; it compiles all unittests of all *compiled* modules, not all *imported* modules. So it does not actually include Phobos unittests. [...] As Steven Schveighoffer [pointed out][1], Phobos unittests are never included in user code, regardless of whether `StdUnittest` is used. The "never" is false, https://d.godbolt.org/z/c4oeYM7rG Unittests inside template code will be added to user code, unless the compiler has determined that the template is already instantiated in Phobos code (the "template culling" that the frontend does, whose behavior is not easily influenced by the programmer). It's always included (or at least it was when I last looked at it), as -unittest implies some form of -allinst. There was some effort to fix this, but I can't remember if the outcome was that it was merged or not. -Steve
Re: Phobos Unittest
On 9/4/21 5:42 AM, Per Nordlöw wrote: On Saturday, 4 September 2021 at 03:18:01 UTC, Paul Backus wrote: As Steven Schveighoffer [pointed out][1], Phobos unittests are never included in user code, regardless of whether `StdUnittest` is used. Yes, but they are lexed and parsed, right? Yes, and I think this is trivially so for any versioned code in the file. Note that lexing and parsing is extremely quick, and I wouldn't focus on trying to trim this out, you won't get much performance out of that. -Steve
Re: Run-time setting of immutable variable?
On 9/2/21 1:17 PM, DLearner wrote: I am looking for a mutable Arr but would like an immutable ArrPtr. Then you want const not immutable. Here is the reason: ```d void main() { int x = 5; immutable int *ptr = cast(immutable int *) assert(*ptr == 5); // ok x = 6; assert(*ptr == 5); // what happens here? } ``` Depending on optimizations and compiler constant folding, that second assert may pass. immutable means "I can never change and *everything I point at* can never change". The compiler is free to use this knowledge to avoid redoing calculations it has already done. I tknows that `*ptr == 5` already, and that can never change, so it just doesn't even bother with the second assert. However, make ptr *const*, and now not only do you not need the cast, but the second assert will fail as expected. ``` `Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's immutable. ``` Surely there is no inconsistency - at run time the array is in a fixed place, so ArrPtr is (or at least should be) a constant, but the contents of the array can vary as the program runs. In D, const and immutable are transitive, which means that you can't have a pointer that is const, but allows changing what it points at. So while a const pointer *may* work for your purposes, you may want a specialized type, or a property function. It depends on how you intend to use `ArrPtr`. Others have given good answers to this problem. -Steve
Re: Run-time setting of immutable variable?
On 9/2/21 12:01 PM, DLearner wrote: Suppose there is a variable that is set once per run, and is (supposed) never to be altered again. However, the value to which it is set is not known at compile time. Example below, variable is 'ArrPtr'; ``` ubyte[10] Arr; // immutable void* ArrPtr; void* ArrPtr; void main() { ArrPtr = cast(void*)Arr[0]; // } ``` Is there a way of getting D to guarantee that ArrPtr is never modified after ``` ArrPtr = cast(void*)Arr[0]; ```] You shouldn't be doing this. `Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's immutable. If you want to guarantee that `ArrPtr` never changes once set, yet still want it to point at mutable data, you need to use a type that does that (like a head mutable or "write once" type), which I believe doesn't exist in phobos. If you don't actually need to mutate the data via `ArrPtr`, you can make it const, and use H.S. Teoh's solution. But you should not use immutable, as the compiler implies that data pointed at is also immutable (and of course, you won't need casting). Make sure you use regular `static this`, not `shared static this`, as your fields are thread-local, not shared. -Steve
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On 8/31/21 8:40 PM, someone wrote: On Tuesday, 31 August 2021 at 14:06:32 UTC, Steven Schveighoffer wrote: The generation of code to output the page depends on the diet file format (i.e. code islands are designated by the leading `-`). However, vibe-d does not require using the diet template system. Does that means I can still get the code islands resolved on a, say, plain-XHTML file ? Or does that means that I should output HTML/XHTML from my own functions instead ? Vibe just provides an output range for use in diet. You can use anything, including just writing the data yourself, or using an alternative template system. Given how templating systems work (and how D allows strings to be used as code using mixins), it's likely pretty trivial to write a simple templating system to do this. All you need is an escape protocol that is unlikely to appear in HTML, and you can probably get away with a 10 line function that doesn't need to actually parse the HTML. Probably. Bit I am not a huge fan of modifying libraries for minor functionality fixes (unless is really really necessary). For whatever reasons I already have custom nginx builds etc etc so I do not want to keep tracking and fixing more software -in the end is a pain-in-the-ass. You aren't modifying anything. Vibe-d provides default access to diet-ng, but you have no obligation to use it. Just use the output range (`HTTPServerResponse.bodyWriter`) and hook up your preferred templating system. I think you are misunderstanding the architecture of vibe. There is no need to replace anything inside vibe to use a different templating system, it does not depend on diet at all, just provides default access. The views directory isn't exactly special either (though there may be code in dub that deals with looking at modification times), nor is the extension `.dt`. Most of the diet compiler is dealing with transforming the pug format into HTML, and proper string interpolation. The code island stuff is quite trivial (just copied as-is). Oh, and I realized I forgot about string interpolation. You definitely want a way to change D expressions into string output. You can still do this with code-islands, but a good template system would handle the boilerplate for you. Which leads me to -- diet really should be split into 2 parts, one that handles the pug parsing and compiling, and one that handles proper string interpolation. Then you could leverage that second part. -Steve
Re: Module import incompatibility
On 8/31/21 11:17 AM, Paul Backus wrote: On Tuesday, 31 August 2021 at 14:09:01 UTC, Steven Schveighoffer wrote: Are you sure this is the problem? `PdfSurface` is not a valid identifier here except for the class. In order to access the package, you need to use `cairo.PdfSurface`. Must've changed since you last checked: ```d // main.d import example; void main() { // Error: incompatible types for `(module example) == (42)`: `void` and `int` assert(example == 42); } ``` ```d // example.d int example = 42; ``` https://run.dlang.io/is/SpEZNF That is a top-level module that has an equivalent name inside. I did say "*as long as* it wasn't a top-level module" ```d // main.d import pkg.mod; void main() { assert mod = 42; } // example.d module pkg.mod; int mod = 42; ``` works fine https://run.dlang.io/is/sQ4Bsa This is why I always try to use a top-level package instead of a module (especially with a common name). -Steve
Re: vibe.d: is it possible to use bare HTML with the functionalty of DIET templates ?
On 8/30/21 8:09 PM, someone wrote: Regarding vibe.d I think I'll give it a try (maybe placing it behind nginx at first) since I do really got a good first-impression ... kudos to the developers/maintainers :) I like the idea of having D at my disposal within a web page, actually, it is a terrific feature to say the least. What I do not like (even a bit) are the pseudo-HTML DIET templates. I can understand they can make life easy for some, but I am not the guy having any trouble writing well-good-structured HTML/XHTML/XML/etc to begin with, nor I am the kind of guy grunting because I will be forced to write closing tags and the like. That being said, my specific question is: Can I use vibe.d *without* DIET templates manually writing say, XHTML 1.1 pages, *while having D* at my disposal with the - prefixes I have seen so far ? The generation of code to output the page depends on the diet file format (i.e. code islands are designated by the leading `-`). However, vibe-d does not require using the diet template system. There are others which probably do what you want (search on code.dlang.org), but I'm a huge fan of diet templates (I actually prefer writing non-template html that way), so I don't have any experience with others. Given how templating systems work (and how D allows strings to be used as code using mixins), it's likely pretty trivial to write a simple templating system to do this. All you need is an escape protocol that is unlikely to appear in HTML, and you can probably get away with a 10 line function that doesn't need to actually parse the HTML. -Steve
Re: Module import incompatibility
On 8/31/21 8:57 AM, frame wrote: On Tuesday, 31 August 2021 at 12:37:51 UTC, bauss wrote: On Tuesday, 31 August 2021 at 12:26:28 UTC, frame wrote: I'm sure it was asked before but can't find the thread: How to deal best with an older library that uses the same class name as module name? I get a lot of `Error: module ABC from file ...ABC.d must be imported with 'import ABC'` Do I need to rename all modules? The problem is that the file doesn't have a module statement so the compiler tries to resolve the module name from the import but is unable to resolve that properly. No, it has one, eg: ```d module cairo.PdfSurface; ``` but the filename is PdfSurface.d and class name also :\ Are you sure this is the problem? `PdfSurface` is not a valid identifier here except for the class. In order to access the package, you need to use `cairo.PdfSurface`. Tango was full of stuff like this, and it worked fine *as long as* it wasn't a top-level module. -Steve
Re: vibe.d community/forum/whatever ?
On 8/29/21 10:39 PM, someone wrote: https://forum.rejectedsoftware.com/groups/rejectedsoftware.vibed/ I've been reading vibe.d tour and some documentation today to get some first impressions. https://vibed.org/community pointed to the link above ... but it seems it is full of crap. It used to be moderated somewhat, but I think they gave up (99% of the messages were porn or spam). Just post here instead, or you can join the [Community discord](https://discord.gg/bMZk9Q4) for more "live" help. -Steve
Re: Is it legal to remove a key from associative array while iterating over aa.keys if a foreach loop?
On 8/29/21 5:02 AM, Mike Parker wrote: On Sunday, 29 August 2021 at 08:55:44 UTC, realhet wrote: Is it safe, or do I have to take a snapsot of the keys range like this? -> You shouldn't remove anything when iterating over `.keys` or `.values`. Use `.byKey` and `.byValue` instead to get ranges that are independent of the aa. This is exactly the opposite! The `.keys` property makes a *copy* of all the keys and puts them into an array. Same thing with `.values`. It is perfectly safe to remove anything from the associative array while iterating one of those arrays. The opposite is true for `.byKey` and `.byValue`. Those yield a range iterating over the actual data in the associative array. Removing an element while iterating one of those could potentially iterate over null or stale data, do not do this. While this might work out in some tests, eventually you will get bit by this, especially if you remove an element you are currently iterating. -Steve
Re: DUB: How to link an external library on Windows 10?
On 8/27/21 11:43 AM, Ki Rill wrote: On Friday, 27 August 2021 at 15:24:14 UTC, Steven Schveighoffer wrote: I suspect your MSVC installation is bad, or there are some other switches causing problems. Hmm... well, I will use the default setup and think about it later. I mostly use Linux, Windows realm is an uncharted territory for me. Take my diagnoses with a grain of salt -- I mostly use MacOS and Linux, and I'm mostly lost on Windows. I was proficient with Visual C++ 5 or so a long time ago ;) -Steve
Re: DUB: How to link an external library on Windows 10?
On 8/27/21 11:19 AM, Ki Rill wrote: On Friday, 27 August 2021 at 14:52:15 UTC, Mike Parker wrote: On Friday, 27 August 2021 at 14:46:56 UTC, Ki Rill wrote: On Friday, 27 August 2021 at 13:54:18 UTC, Steven Schveighoffer wrote: [...] How do I tell DUB where to look for `raylibdll.lib` and `raylib.dll`? Via `lflags` section? What if I put them in a different folder instead of the project's directory? Yes. The path goes in the lflags directive using whatever the linker-specific flag is. I assume for lld it's `-Lpath`. For MS link it's `/LIBPATH:path`. To clarify, the .dll file's path is not embedded into the binary. You have to add it's path to your "Path" environment variable in order for your game to load it. But you do need the /LIBPATH option to tell it where to find the .lib file. I've added lfags: ``` "lflags": ["/LIBPATH:C:\\Users\\Username\\Desktop\\test\\source\\"] ``` But now it cannot find the following: ``` msvcrt120.lib OLDNAMES.lib shell32.lib ``` I think `lfags` overrides the default search path and I need to add it manually as well. But what is that path on Windows? That shouldn't happen. I've never had to tell it where the default libraries are. For sure the lflags does NOT override the default library search paths. I suspect your MSVC installation is bad, or there are some other switches causing problems. -Steve
Re: DUB: How to link an external library on Windows 10?
On 8/27/21 10:35 AM, Ki Rill wrote: On Friday, 27 August 2021 at 13:54:18 UTC, Steven Schveighoffer wrote: In the end, I got it to build and run, but I'd highly recommend just linking against the `raylibdll.lib` and using the dll. Steve, thank you! I got it working with `raylibdll.lib`! Yes, either 3.5.0 or 3.7.0, they now build with 2 types of libs, static and dynamic. The raylib.lib file is for static linking, the raylibdll.lib file is for DLL. Glad you got it working! 4. put `raylib.dll` and `raylibdll.lib` into your project's folder (into the same directory, where you have `dub.json`) You know, I taught a class using raylib and D (I learned a lot from your video series, thanks!), and I didn't even think about just copy the libraries to your project directory as a "step". Instead I had them put in the /LIBDIR flags to wherever they installed it. This way is MUCH easier, I think I'll switch to that. dub in general has some rough edges when linking against libraries that aren't in default locations. Having to edit the dub.json file is sub-par. -Steve
Re: DUB: How to link an external library on Windows 10?
On 8/27/21 9:21 AM, Ki Rill wrote: I have a Raylib project on Windows using DUB. I've added raylib-d via `dub add`. But what I can't figure out is how to tell DUB to link against raylib library. I have the following project structure: ``` -> source ---> app.d -> libraylib.a -> raylib.dll -> etc... ``` I'd like to use either .a or .dll. Do you have any ideas? I spent a lot of time trying to figure this out (someone in discord really wanted to link statically for some reason). I FINALLY got a statically linked exe, but it's not worth the effort. I had to: 1. update my msvc build tools to match what was used for the official release (alternatively, you can rebuild the raylib library with your tools, otherwise you get cryptic errors like `fatal error C1900: Il mismatch between 'P1' version '20210113' and 'P2' version '20190715'`). 2. pass in cryptic linker options like `/NODEFAULTLIB:libcmt`, etc. 3. Link against extra libraries until the linker errors disappear (google search for missing symbols to see what libraries those symbols are in). My eventual resulting dub.json looked like (you can guess where I put things): ```json { "name": "rps-explosion", "dependencies": { "jsoniopipe": "~>0.1.3", "enet-d": "~>0.0.1", "raylib-d": "~>3.1.0" }, "libs": ["enet", "raylib", "ws2_32", "winmm", "msvcrt", "user32", "gdi32"], "lflags": ["/LIBPATH:C:\\dprojects\\enet-1.3.17", "/LIBPATH:C:\\dprojects\\raylib-3.7.0_win64_msvc16\\lib", "/NODEFAULTLIB:libcmt", "/NODEFAULTLIB:libvcruntime"] } ``` This config also included `enet-d` so some of the linker options are for that lib. In the end, I got it to build and run, but I'd highly recommend just linking against the `raylibdll.lib` and using the dll. -Steve
Re: A way to mixin during runtime?
On 8/27/21 6:34 AM, Kirill wrote: On Friday, 27 August 2021 at 09:51:46 UTC, Mathias LANG wrote: On Friday, 27 August 2021 at 06:52:10 UTC, Kirill wrote: Is there a way to do mixin or similar during runtime? I'm trying to read a csv file and extract data types. Any ideas on how this should be approached in D are greatly appreciated. You cannot mixin at runtime. However, it is fairly easy to map a finite and CT-know set of argument to runtime arguments via `static foreach`. Could you give us example of the content of your CSV file and what you are trying to do ? Each csv file will be different. For example: ``` name;surname;age;grade Alex;Wong;18;87 John;Doe;19;65 Alice;Doe;18;73 etc... ``` I'd like to extract the data types automatically. For instance, if using tuples: ``` Tuple!(string, string, int, int) ... ``` instead I'd like to have: ``` auto mytuple = read_csv(path); // returns Tuple!(string, string, int, int)[] ``` So you can't build "new types" at runtime that are usable after your code is compiled. But there are options: 1. You can parse the CSV at compile-time using `import("types.csv");` and then processing the resulting string using CTFE (not sure if std.csv does this, but I'd expect it to). Then you can use the resulting thing to generate string mixins that can generate types. This has the drawback that you need to recompile when your csv input changes. 2. You can create a dynamic type that deals with the CSV data. It looks from your CSV data you are inferring the "type" from the data itself, which is complex in itself. In this case, you'd use it kind of like a JSON object, where you index the fields by name instead of using `obj.name`, and you'd have to extract the type dynamically from the type inference you'd have to write. This is pretty much what std.csv does, though you can dress it up a bit more. Without the CSV telling you types, it's hard to make something "easy". I have written code that extracts from JSON data and database data serializable struct types, and builds a D file, but it's never clean-cut, and sometimes you have to hand-edit that stuff. This is about as "easy" as it gets, just have the computer do most of the heavy lifting, and then massage it into something usable. -Steve
Re: A little help with Ranges
On 8/27/21 12:41 AM, Merlin Diavova wrote: On Friday, 27 August 2021 at 04:01:19 UTC, Ali Çehreli wrote: On 8/26/21 7:17 PM, Merlin Diavova wrote: [...] Then the operations downstream will not produce any results. For example, the array will be empty below: import std.stdio; import std.range; import std.algorithm; import std.string; import std.functional; void main() { auto significantLines = stdin .byLineCopy .map!strip .filter!(not!empty) .filter!(line => line.front != '#') .array; if (significantLines.empty) { writeln("There were no significant lines."); } else { writefln!"The lines: %-(\n%s%)"(significantLines); } } Ali And there it is! I was missing ```d .filter!(not!empty) ``` My code now works exactly how I wanted. Thanks! Be careful with this! `not!empty` is *only* working because you are using arrays (where `empty` is a UFCS function defined in std.range). Other ranges this will not work on. Instead, I would recommend a lambda (which will work with arrays too): ```d .filter!(r => !r.empty) ``` -Steve
Re: foreach() behavior on ranges
On 8/25/21 12:46 PM, Joseph Rushton Wakeling wrote: On Wednesday, 25 August 2021 at 10:59:44 UTC, Steven Schveighoffer wrote: structs still provide a mechanism (postblit/copy ctor) to properly save a forward range when copying, even if the guts need copying (unlike classes). In general, I think it was a mistake to use `.save` as the mechanism, as generally `.save` is equivalent to copying, so nobody does it, and code works fine for most ranges. Consider a struct whose internal fields are just a pointer to its "true" internal state. Does one have any right to assume that the postblit/copy ctor would necessarily deep-copy that? In a world where copyability means it's a forward range? Yes. We aren't in that world, it's a hypothetical "if we could go back and redesign". If that struct implements a forward range, though, and that pointed-to state is mutated by iteration of the range, then it would be reasonable to assume that the `save` method MUST deep-copy it, because otherwise the forward-range property would not be respected. With that in mind, I am not sure it's reasonable to assume that just because a struct implements a forward-range API, that copying the struct instance is necessarily the same as saving the range. Technically this is true. In practice, it rarely happens. The flaw of `save` isn't that it's an unsound API, the flaw is that people get away with just copying, and it works 99.9% of the time. So code is simply untested with ranges where `save` is important. Indeed, IIRC quite a few Phobos library functions program defensively against that difference by taking a `.save` copy of their input before iterating over it. I'd be willing to bet $10 there is a function in phobos right now, that takes forward ranges, and forgets to call `save` when iterating with foreach. It's just so easy to do, and works with most ranges in existence. What should have happened is that input-only ranges should not have been copyable, and copying should have been the save mechanism. Then it becomes way way more obvious what is happening. Yes, this means forgoing classes as ranges. I think there's a benefit of a method whose definition is explicitly "If you call this, you will get a copy of the range which will replay exactly the same results when iterating over it". Just because the meaning of "copy" can be ambiguous, whereas a promise about how iteration can be used is not. The idea is to make the meaning of a range copy not ambiguous. -Steve
Re: scope(exit) with expected library
On 8/25/21 10:58 AM, WebFreak001 wrote: Hm I'm not quite seeing how the error handler is related to an "Expected type interface" that the compiler could expect. This would be without compiler changes. Currently with exceptions the scope things are implemented using try-catch-finally, this would be even simpler: ```d scope(exit) exit(); scope(success) success(); scope(failure) failure(); return something(); ``` lowers to ```d auto ret = something(); if (ret.isError) failure(); if (!ret.isError) success(); exit(); return ret; ``` for all return statements. I might be missing some obvious drawbacks here but I think this sounds reasonable and comparable with the try-catch-finally lowering. It does sound pretty reasonable. But overloading these existing features might make things confusing. As Paul Backus suggested the compiler could check if the return type has for example `is(typeof(return.isError) : bool)` and maybe also if the function is `nothrow`. Another approach is to let the compiler deal with the error handling and not muddy your return type. Swift does something similar, where it rewrites the throw/catch into a standard return and doesn't do actual thrown exceptions. There are some caveats, but if we could fit this kind of error handling into mostly-similar syntax (i.e. the same ease of exceptions without the actual problems that exceptions and stack unwinding bring), it might make things much easier to transition. -Steve
Re: scope(exit) with expected library
On 8/25/21 10:42 AM, Steven Schveighoffer wrote: I think it's possible to work with some mechanics that aren't necessarily desirable. Something like: One has to weigh how much this is preferred to actual exception handling... If something like DIP1008 could become usable, it might alleviate even the need for such things. -Steve
Re: scope(exit) with expected library
On 8/25/21 10:22 AM, Paul Backus wrote: On Wednesday, 25 August 2021 at 14:04:54 UTC, WebFreak001 wrote: Would it be possible to extend `scope(exit)` and `scope(success)` to trigger properly for functions returning `Expected!T` as defined in the [expectations](https://code.dlang.org/packages/expectations) and [expected](https://code.dlang.org/packages/expected) DUB libraries? For example is it possible to make this work as expected: ```d Expected!int divide(int a, int b) nothrow { scope (failure) writeln("division failed"); scope (success) writeln("division succeeded"); if (b == 0) return err!int("division by zero"); return ok(a / b); } ``` Probably the only principled way to make this work would be to define some kind of "concept"/structural interface that's recognized by the compiler to mean "this is an error-handling type", in the same way that the compiler recognizes `empty`/`front`/`popFront` to mean "this is an iterable type". Even then, it would require some pretty invasive language changes (and some pretty gnarly code in the compiler), but it's at least *theoretically* possible. I think it's possible to work with some mechanics that aren't necessarily desirable. Something like: ```d ErrorHandler error = registerErrorHandler; error.onFailure({writeln("division failed");}); error.onSuccess({writeln("division succeeded");}); ... ``` On returning `err`, the registration would trigger a flag saying an error is occurring, and call the right callback when `ErrorHandler` is destructing. The cleanup of the return value would clean up the error condition. It would be messy and likely brittle. I've also advocated in the past that it would be nice to have access to the things that are causing the success, failure, etc. Like `scope(failure, exception) writeln("Exception being thrown is ", exception)` Could be extended to: ```d scope(success, r) if(r.isError) writeln("division failed"); else writeln("division succeeded"); ``` That `scope(success)` kinda sucks though... -Steve
Re: foreach() behavior on ranges
On 8/25/21 7:26 AM, Alexandru Ermicioi wrote: On Wednesday, 25 August 2021 at 11:04:35 UTC, Steven Schveighoffer wrote: It never has called `save`. It makes a copy, which is almost always the equivalent `save` implementation. Really? Then what is the use for .save method then? The only reason I can find is that you can't declare constructors in interfaces hence the use of the .save method instead of copy constructor for defining forward ranges. The `save` function was used to provide a way for code like `isForwardRange` to have a definitive symbol to search for. It's also opt-in, whereas if we used copying, it would be opt-out. Why a function, and not just some enum? Because it should be something that has to be used, not just a "documenting" attribute if I recall correctly. Keep in mind, UDAs were not a thing yet, and compile-time introspection was not as robust as it is now. I'm not even sure you could disable copying. We have now two ways of doing the same thing, which can cause confusion. Best would be then for ranges to hide copy constructor under private modifier (or disable altoghether), and force other range wrappers call .save always, including foreach since by not doing so we introduce difference in behavior between ref and value forward ranges (for foreach use). There would be a huge hole in this plan -- arrays. Arrays are the most common range anywhere, and if a forward range must not be copyable any way but using `save`, it would mean arrays are not forward ranges. Not to mention that foreach on an array is a language construct, and does not involve the range interface. -Steve
Re: foreach() behavior on ranges
On 8/25/21 6:06 AM, Alexandru Ermicioi wrote: On Wednesday, 25 August 2021 at 08:15:18 UTC, frame wrote: I know, but foreach() doesn't call save(). Hmm, this is a regression probably, or I missed the time frame when foreach moved to use of copy constructor for forward ranges. Do we have a well defined description of what input, forward and any other well known range is, and how it does interact with language features? For some reason I didn't manage to find anything on dlang.org. It never has called `save`. It makes a copy, which is almost always the equivalent `save` implementation. -Steve
Re: foreach() behavior on ranges
On 8/25/21 4:31 AM, frame wrote: On Tuesday, 24 August 2021 at 21:15:02 UTC, Steven Schveighoffer wrote: I'm surprised you bring PHP as an example, as it appears their foreach interface works EXACTLY as D does: Yeah, but the point is, there is a rewind() method. That is called every time on foreach(). It seems what you are after is forward ranges. Those are able to "rewind" when you are done with them. It's just not done through a rewind method, but via saving the range before iteration: ```d foreach(val; forwardRange.save) { ... break; } // forwardRange hasn't been iterated here ``` -Steve
Re: foreach() behavior on ranges
On 8/25/21 6:06 AM, Joseph Rushton Wakeling wrote: On Tuesday, 24 August 2021 at 09:15:23 UTC, bauss wrote: A range should be a struct always and thus its state is copied when the foreach loop is created. That's quite a strong assumption, because its state might be a reference type, or it might not _have_ state in a meaningful sense -- consider an input range that wraps reading from a socket, or that just reads from `/dev/urandom`, for two examples. Deterministic copying per foreach loop is only guaranteed for forward ranges. structs still provide a mechanism (postblit/copy ctor) to properly save a forward range when copying, even if the guts need copying (unlike classes). In general, I think it was a mistake to use `.save` as the mechanism, as generally `.save` is equivalent to copying, so nobody does it, and code works fine for most ranges. What should have happened is that input-only ranges should not have been copyable, and copying should have been the save mechanism. Then it becomes way way more obvious what is happening. Yes, this means forgoing classes as ranges. -Steve
Re: foreach() behavior on ranges
On 8/24/21 2:12 PM, frame wrote: You can call `popFront` if you need to after the loop, or just before the break. I have to say, the term "useless" does not even come close to describing ranges using foreach in my experience. I disagree, because foreach() is a language construct and therefore it should behave in a logic way. The methods are fine in ranges or if something is done manually. But in case of foreach() it's just unexpected. I can't agree at all. It's totally expected. If you have a for loop: ```d int i; for(i = 0; i < someArr.length; ++i) { if(someArr[i] == desiredValue) break; } ``` You are saying, "compiler, please execute the `++i` when I break from the loop because I already processed that one". How can that be expected? I would *never* expect that. When I break, it means "stop the loop, I'm done", and then I use `i` which is where I expected it to be. It becomes useless for foreach() because you can't rely on them if other code breaks the loop and you need to use that range, like in my case. But also for ranges - there is no need for a popFront() if it is not called in a logic way. Then even empty() could fetch next data if needed. It only makes sense if language system code uses it in a strictly order and ensures that this order is always assured. There is no problem with the ordering. What seems to be the issue is that you aren't used to the way ranges work. What's great about D is that there is a solution for you: ```d struct EagerPopfrontRange(R) { R source; ElementType!R front; bool empty; void popFront() { if(source.empty) empty = true; else { front = source.front; source.popFront; } } } auto epf(R)(R inputRange) { auto result = EagerPopfrontRange!R(inputRange); result.popFront; // eager! return result; } // usage foreach(v; someRange.epf) { ... } ``` Now if you break from the loop, the original range is pointing at the element *after* the one you last were processing. It's not a bug. So there is no need to "handle" it. The pattern of using a for(each) loop to align certain things occurs all the time in code. Imagine a loop that is looking for a certain line in a file, and breaks when the line is there. Would you really want the compiler to unhelpfully throw away that line for you? I don't get this point. If it breaks from the loop then it changes the scope anyway, so my data should be already processed or copied. What is thrown away here? Why does the loop have to contain all your code? Maybe you have code after the loop. Maybe the loop's purpose is to align the range based on some criteria (e.g. take this byLine range and prime it so it contains the first line of the thing I'm looking for). And if that is what you want, put `popFront` in the loop before you exit. You can't "unpopFront" something, so this provides the most flexibility. Yes, this is the solution but not the way how it should be. If the programmer uses the range methods within the foreach-loop then you would expect some bug. There shouldn't be a need to manipulate the range just because I break the foreach-loop. You shouldn't need to in most circumstances. I don't think I've ever needed to do this. And I use foreach on ranges all the time. Granted, I probably would use a while loop to align a range rather than foreach. Java, for example just uses next() and hasNext(). You can't run into a bug here because one method must move the cursor. This gives a giant clue as to the problem -- you aren't used to this. Java's iterator interface is different than D's. It consumes the element as you fetch it, instead of acting like a pointer to a current element. Once it gives you the element, it's done with it. D's ranges are closer to a C++ iterator pair (which is modeled after a pair of pointers). PHP has a rewind() method. So any foreach() would reset the range or could clean up before next use of it. I'm surprised you bring PHP as an example, as it appears their foreach interface works EXACTLY as D does: ```php $arriter = new ArrayIterator(array(1, 2, 3, 4)); foreach($arriter as $val) { if ($val == 2) break; } print($arriter->current()); // 2 ``` But D just lets your range in an inconsistent state between an iteration cycle. This feels just wrong. The next foreach() would not continue with popFront() but with empty() again - because it even relies on it that a range should be called in a given order. As there is no rewind or exit-method, this order should be maintained by foreach-exit too, preparing for next use. That's it. You don't see a bug here? I believe the bug is in your expectations. While Java-like iteration would be a possible API D could have chosen, it's not what D chose. -Steve
Re: foreach() behavior on ranges
On 8/24/21 4:36 AM, frame wrote: Consider a simple input range that can be iterated with empty(), front() and popFront(). That is comfortable to use with foreach() but what if the foreach loop will be cancelled? If a range isn't depleted yet and continued it will supply the same data twice on front() in the next use of foreach(). For some reason, foreach() does not call popFront() on a break or continue statement. continue calls `popFront`. break does not. There is no way to detect it except the range itself tracks its status and does an implicit popFront() if needed - but then this whole interface is some kind of useless. You can call `popFront` if you need to after the loop, or just before the break. I have to say, the term "useless" does not even come close to describing ranges using foreach in my experience. There is opApply() on the other hand that is designed for foreach() and informs via non-0-result if the loop is cancelled - but this means that every range must implement it if the range should work in foreach() correctly? `opApply` has to return different values because it needs you to pass through its instructions to the compiler-generated code. The compiler has written the delegate to return the message, and so you need to pass through that information. The non-zero result is significant, not just non-zero. For instance, if you end with a `break somelabel;` statement, it has to know which label to go to. The correct behavior for `opApply` should be, if the delegate returns non-zero, return that value immediately. It should not be doing anything else. Would you be happy with a `break somelabel;` actually triggering output? What if it just continued the loop instead? You don't get to decide what happens at that point, you are acting as the compiler. This is very inconsistent. Either foreach() should deny usage of ranges that have no opApply() method or there should be a reset() or cancel() method in the interfaces that may be called by foreach() if they are implemented. How do you handle that issue? Are your ranges designed to have this bug or do you implement opApply() always? It's not a bug. So there is no need to "handle" it. The pattern of using a for(each) loop to align certain things occurs all the time in code. Imagine a loop that is looking for a certain line in a file, and breaks when the line is there. Would you really want the compiler to unhelpfully throw away that line for you? And if that is what you want, put `popFront` in the loop before you exit. You can't "unpopFront" something, so this provides the most flexibility. -Steve
Re: Concurrency message passing
On 8/17/21 2:36 PM, JG wrote: Thanks for the suggestions and explanations. I am not sure what to do in my case though. The situation is as follows. I have a struct that is populated via user input not necessarily at single instance (so that seems to rule out immutable). On the other hand while it is being populate it is only accessible from one thread so that makes using shared messy. After being populated it should be passed to the other thread and no references are kept. You are allowed to cast to immutable if no other mutable references are used. I recommend using `assumeUnique`. What I am doing currently is populating the struct and casting to shared when I push into a synchronized queue (no references to its data are kept in the first thread). Is what I am doing wrong and can it be achieved using message passing? Yeah, build it like Ali says, and then cast in order to pass it. -Steve
Re: simple (I think) eponymous template question ... what is proper idimatic way ?
On 8/17/21 2:11 PM, james.p.leblanc wrote: Evening All, Eponymous templates allow a nice calling syntax. For example, "foo" here can be called without needing the exclamation mark (!) at calling sites. We see that foo is restricting a, and b to be of the same type ... so far, so good. auto foo(T)(T a, T b) { ... } Now, suppose I need to restrict "T" only certain subsets of variable types. I can imagine putting in some "static if" statements in my function body, is one solution. (Also a bit ugly as the allowed types might grow). Is there a more elegant way, to do this? [Template constraints](https://dlang.org/spec/template.html#template_constraints). -Steve
Re: Non-consistent implicit function template specializations
On 8/17/21 2:07 PM, Rekel wrote: On Tuesday, 17 August 2021 at 16:24:38 UTC, Steven Schveighoffer wrote: All these are calling with array literals, which default to dynamic arrays, not static arrays. I realise that is their default, though in this scenario they should (I believe) be used as static arrays. (This works for me in any case) According to my tests, it prefers the `T` version over the static array version. Which leads me to believe that it prefers a dynamic array over a static one. In fact, if I comment out the `T` version, it doesn't compile. It literally will not pick that specialization, even if it can interpret the literal that way. which is really bizarre, since if you do it without specializations, but just spelling out all the template components (as in your alternative workaround), it WILL pick that one over a dynamic array one. -Steve
Re: Non-consistent implicit function template specializations
On 8/17/21 10:20 AM, Rekel wrote: As my post was not the actual cause of my issue (my apology for the mistake), I think I have found the actual reason I'm currently having problems. This seems to be related to a (seeming, I might be wrong) inability to specialize over both 1d and 2d arrays separately. (If constraining the length to values.) This brings me to 2 questions. 1. How does one specialize a template for both 1d and 2d arrays at the same time? 2. Are there any plans to rework templates? like: - Making `template TFoo(T : T[])` illegal. This makes little sense to me however I look at it, and as several people have advised against it it's confusing it's in the docs. (21.4.1) - Changing the way priorities are set using specializations in general, to make them less pitfall-y. - Allow for 2+d length specification. At the moment `T[][L]` works while `T[L][L]` does not seem to. You should try out things individually to see if they at least work. ```d void foo(T)(T a){...} void foo(T:U[L], uint L)(T a){...} This is an invalid specification, what is U? Did you mean: void foo(T: U[L], U, uint L)(T a) {...} void foo(T:U[L][L], uint L)(T a){...} // Never matched Apart from another missing U, this is only a SQUARE 2d-array (both dimensions the same), your example below only calls with a 1x2 array. void foo(T:U[L], U:V[L], V uint L)(T a){...} // Never matched (alternatively) I don't think you need this, and I had to comment it out, or the compiler wouldn't build. // Should work with void main(string[] args) { foo([[1],[2]]); foo([1,2]); foo(1); } ``` All these are calling with array literals, which default to dynamic arrays, not static arrays. -Steve
Re: How to get element type of a slice?
On 8/17/21 8:21 AM, Ferhat Kurtulmuş wrote: Hello folks, Hope everyone is doing fine. Considering the following code, in the first condition, I am extracting the type Point from the slice Point[]. I searched in the std.traits, and could not find a neater solution something like ElementTypeOf!T. Is there any neater solution for it? Thanks in advance. ```d static if (isArray!VecPoint){ VecPoint dummy; alias Point = typeof(dummy[0]); } else static if (isRandomAccessRange!VecPoint){ alias ASeq2 = TemplateArgsOf!VecPoint; alias Point = ASeq2[0]; } else static assert(0, typeof(VecPoint).stringof ~ " type is not supported"); ``` If you want the element type of a range (i.e. the thing returned by `range.front`), you can use `ElementType!T` (from std.range.primitives). This returns the element type of the range, which for every array *except* character arrays, gives you the element type of the array. If you want always the element type of the array, even for auto-decoded ranges, use `ElementEncodingType!T`. If you know it's an array, you can just use Paul's solution. Your `isRandomAccessRange` branch seems very suspect. -Steve
Re: Concurrency message passing
On 8/17/21 7:05 AM, JG wrote: Hi I have a program with two threads. One thread produces data that is put in a queue and then consumed by the other thread. I initially built a custom queue to do this, but thought this should have some standard solution in D? I looked at std.concurrency and thought that message passing could be used. However, the problem is that I get the following error. Error: static assert: "Aliases to mutable thread-local data not allowed." I am not sure how to solve this. Maybe message parsing isn't the correct solution? Is there some standard solution to this in D? Data with references needs to be marked either immutable or shared in order to be passed using std.concurrency. D is strict about not sharing thread-local data, because then you can use the type system to prove lock-free code is valid. However, data that has no references (aliases) should be passable regardless of mutability, because you are passing a copy. -Steve
Re: What exactly are the String literrals in D and how they work?
On 8/15/21 2:10 AM, rempas wrote: So when I'm doing something like the following: `string name = "John";` Then what's the actual type of the literal `"John"`? In the chapter [Calling C functions](https://dlang.org/spec/interfaceToC.html#calling_c_functions) in the "Interfacing with C" page, the following is said: Strings are not 0 terminated in D. See "Data Type Compatibility" for more information about this. However, string literals in D are 0 terminated. Which is really interesting and makes me suppose that `"John"` is a string literal right? However, when I'm writing something like the following: `char *name = "John";`, then D will complain with the following message: Error: cannot implicitly convert expression `"John"` of type `string` to `char*` Which is interesting because this works in C. If I use `const char*` instead, it will work. I suppose that this has to do with the fact that `string` is an alias for `immutable(char[])` but still this has to mean that the actual type of a LITERAL string is of type `string` (aka `immutable(char[])`). Another thing I can do is cast the literal to a `char*` but I'm wondering what's going on under the hood in this case. Is casting executed at compile time or at runtime? So am I going to have an extra runtime cost having to first construct a `string` and then ALSO cast it to a string literal? I hope all that makes sense and the someone can answer, lol Lots of great responses in this thread! I wanted to stress that a string literal is sort of magic. It has extra type information inside the compiler that is not available in the normal type system. Namely that "this is a literal, and so can morph into other things". To give you some examples: ```d string s = "John"; immutable(char)* cs = s; // nope immutable(char)* cs2 = "John"; // OK! wstring ws = s; // nope wstring ws2 = "John"; // OK! ``` What is going on? Because the compiler knows this is a string *literal*, it can modify the type (and possibly the data itself) at will to match what you are assigning it to. In the case of zero-terminated C strings, it allows usage as a pointer instead of a D array. In the case of different width strings (wstring uses 16-bit code-units), it can actually transform the underlying data to what you wanted. Note that even when you do lose that "literal" magic by assigning to a variable, you can still rely on D always putting a terminating zero in the data segment for a string literal. So it's valid to just do: ```d string s = "John"; printf(s.ptr); As long as you *know* the string came from a literal. -Steve
Re: How to extend the string class to return this inside the square bracket?
On 8/13/21 7:23 PM, Marcone wrote: On Friday, 13 August 2021 at 23:08:07 UTC, jfondren wrote: On Friday, 13 August 2021 at 22:09:59 UTC, Marcone wrote: Isn't there some unario operator template that I can use with lambda to handle a string literal? So, something other than an exact "lit"[0..this.xx(..)] syntax is fine? What didn't you like about `"Hello World!".findSplit("o")[0].writeln;` then? What is a real example of something you want to do? writeln("Hello World!"[x.indexOf("e")..x.indexOf("r")]); indexOf()is just a simple example, not the goal. I want handle literal inside [] like it bellow, but in literal: string x = "Hello World!"; writeln(x[x.indexOf("e")..x.indexOf("r")]); Operator overloading is only available to custom types (structs or classes), and not to arrays. You can create a type to do what you want. e.g.: ```d struct SliceByIndexOf { string s; auto opIndex(size_t[2] idxs) { return SliceByIndexOf(s[ idxs[0] .. idxs[1]]); } size_t[2] opSlice(size_t dim : 0)(string s1, string s2) { import std.string; return [s.indexOf(s1), s.indexOf(s2)]; } string toString() { return s; } } auto sbio(string s) { return SliceByIndexOf(s); } void main() { import std.stdio; writeln("Hello World!".sbio["e" .. "r"]); // "ello Wo" } ``` -Steve
Re: How to extend the string class to return this inside the square bracket?
On 8/13/21 5:05 PM, Marcone wrote: How to extend the string class to return this inside the square bracket the same way opDollar $ returns the length of the string? Thank you. import std; void main(){ writeln("Hello World!"[0..this.indexOf("o")]); } There is no string class to extend. `$` is a special token the compiler changes to `arr.length` for arrays. -Steve
Re: I do not understand copy constructors
On 8/13/21 4:58 PM, Paul Backus wrote: On Friday, 13 August 2021 at 15:26:15 UTC, Steven Schveighoffer wrote: The issue is that you can't convert const (or immutable or mutable) to inout implicitly, and the member variable is inout inside an inout constructor. Therefore, there's no viable copy constructor to call for the member, and the outer copy constructor cannot be generated. I'm not quite sure I follow this. Are you saying that the constructor call is typechecked as if it were written like this: ```d this.field = this.field.__ctor(rhs.field); ``` ...and not like this? ```d this.field.__ctor(rhs.field); ``` Because I can see how the first version would involve an const-to-inout conversion, but the second version looks like it ought to work. My point was just that `ref inout` normally binds to `ref const`. Example: ```d void foo(ref const int a) { writeln("hi, a is ", a); } void bar(ref inout int b) { foo(b); // fine } ``` You implied in your statement that it was the ref-ness that prevents the call. Your simplified example was also a bit off, it was a double indirection of a ref array (which is definitely forbidden to be implicit cast). But for constructors it's not the same. Essentially because constructors have different rules for what they can do with their inputs (the inout `this` parameter can be assigned to for the member's first assignment). What I was trying to say (poorly) is that inside the inout copy ctor, you can actually call the const `A` copy constructor with an input of the other `inout A`. You just can't call it on the member (or assign it to the member), because that would allow some bad things to happen in some cases. -Steve
Re: Help with Win32: PostQuitMessage(0) doesn't post WM_QUIT apparently, because the message loop is not exited.
On 8/13/21 3:59 PM, Mike Parker wrote: On Friday, 13 August 2021 at 16:18:06 UTC, Ruby The Roobster wrote: Context for this: I am creating a module of my own, and this is a class contained in the module. You will notice that after calling this class' constructor anywhere in a Win32 API program, that the program doesn't close after the window is closed. You're hanging in `Runtime.terminate`. That's because of your `Entity` destructor, specifically this line: entitytable.length -= 1; Comment it out and the program exits successfully. You aren't supposed to be manipulating GC-managed memory via class destructors. You can not rely on that memory being valid at the time that it's accessed in the destructor---the object may already have been destroyed. Nondeterministic destruction is the price you pay for letting the GC manager your object memory. Of course, in this case, the problem will only crop up at termination since the array is declared at module scope so will be live up until the GC shuts down. But still, not something you should be doing. The runtime will help you by throwing an error if you do anything that directly triggers an allocation, like calling `new` or performing an array append. But it won't help you with anything else. Someone more versed than I with the GC innards may be able to answer whether an error should be thrown here as well, or if this goes under the undefined behavior category. Well, subtracting the length doesn't do much, you aren't actually accessing the array block, you are just changing the reference (which lives in thread-local storage). I kind of feel like the whole entity table thing is not correct anyway. Did you (Mike) also comment out the `did` call? Because that looks more suspicious to me. What it is doing is going through all the entities from the removed one on and setting their id to 1 less. HOWEVER, it's not actually *moving* the entities down in the array. So for instance, if you have 3 entities `[e(0), e(1), e(2)]` then what happens when you remove e(1) is it changes their ids to `[e(0), e(0), e(1)]` and then resizes the array to strip off the last one, so you get the destroyed entity still in the table, and the one that used to be e(2) out of the table (though its id is set to 1 now). The result will be `[e(0), e(0)]`, with the second one pointing to an invalid block. However, you will NEVER have an entity be destroyed, because there is always a reference to it in the table! They will only get destroyed at the end, via `terminate` where things are destroyed deterministically. I think you are right that he shouldn't be changing that `entitytable` thing in the dtor. I also think, the memory management being used there is super-sketchy. Without knowing why you need to keep the table around in the first place, I'm unsure how it should be fixed. I suspect there is a memory access violation or some other issue that's causing it to crash rather than exit normally. -Steve
Re: I do not understand copy constructors
On 8/12/21 12:12 PM, Paul Backus wrote: The reason for this is a bit subtle. Normally, `inout` can convert to `const`, so you might expect that the `const` copy constructor could be used to construct a copy of an `inout` object. However, copy constructors take their arguments by `ref`, and implicit conversions are not allowed for arguments passed to `ref` parameters. (I cannot find a citation in the spec for this, but you can verify it yourself.) implicit const conversions are possible via a single ref, but not through a double reference. In this case, it's not the passing of the inout object to the const constructor. The issue is that you can't convert const (or immutable or mutable) to inout implicitly, and the member variable is inout inside an inout constructor. Therefore, there's no viable copy constructor to call for the member, and the outer copy constructor cannot be generated. As a side note, inout actually *can* bind to double references of any mutability, unlike const, which is a nice feature that is seldom talked about. -Steve
Re: aliasing functions with function arguments as well ??
On 8/13/21 11:04 AM, james.p.leblanc wrote: Dear All, How does one use 'alias' to incorporate function arguments as well? (I believe this is possible, from some of the examples of aliasSeq, and the traits.Parameters documentation. However, I was unable to come up with anything that works.) What should replace the question marks (???) below? double bar( int a, double x){ return a*x: } template foo(T){ static if ( is(T==int) ){ alias ??? = ??? } else{ alias ??? = ??? } } // when T == int, I desire the aliasing to produce resulting code: foo( int a) = bar( int a, 42.33); // when T == double, I desire: foo( double x) = bar( 7, x); Thanks kindly for any information! James PS I am aware of the "struct holding a function allowing multiple dispatch concept" ... while that would fit quite okay here in my simple example, it isn't appropriate for my real use. There isn't a way to alias it. You can wrap it though, and hope the inliner takes care of the difference: ```d auto foo(T)(T arg) { static if(is(T == int)) return bar(arg, 42.33); else return bar(7, arg); } ``` -Steve
Re: I do not understand copy constructors
On 8/12/21 10:08 AM, Learner wrote: On Thursday, 12 August 2021 at 13:56:17 UTC, Paul Backus wrote: On Thursday, 12 August 2021 at 12:10:49 UTC, Learner wrote: That worked fine, but the codebase is @safe: ```d cast from `int[]` to `inout(int[])` not allowed in safe code ``` So copy constructors force me to introduce trusted methods, while that was not necessary with postblits? A postblit would simply ignore the type qualifier--which can lead to undefined behavior. (Scroll down to the paragraph that begins "An unqualified postblit..." under ["Struct Postblits"][1] in the spec.) The copy constructor merely forces you to be honest about the safety of your code. In your case, I would recommend encapsulating the unsafe cast in a function like the following: ```d T[] dupWithQualifiers(T[] array) { auto copy = array.dup; return (() @trusted => cast(T[]) copy)(); } ``` You can then use this function in place of `dup` in your copy constructor. [1]: https://dlang.org/spec/struct.html#struct-postblit Thank you, now everything is more clear. A last question, if you do not mind, just to better understand inout. It seems a shortcut to avoid repeating the same function body for mutable, const, and immutable. Why the following code is not equal to the single inout constructor? struct A { int[] data; //this(ref return scope inout A rhs) inout { /*body*/ } this(ref return scope Timestamp rhs) { /*body*/ } this(ref return scope const Timestamp rhs) const { /*body*/ } this(ref return scope immutable Timestamp rhs) immutable { /*body*/ } } Error: Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable Inout is compatible only with inout, and not with the unrolled code it implies? inout is not like a template. It's a separate qualifier that generates only one function (not 3 unrolled ones). It's sort of viral like const is viral -- all underlying pieces have to support inout in order for you to write inout functions. -Steve
Re: equivalent of std.functional.partial for templates?
On Wednesday, 11 August 2021 at 14:08:59 UTC, Paul Backus wrote: On Wednesday, 11 August 2021 at 14:03:50 UTC, Paul Backus wrote: On Wednesday, 11 August 2021 at 14:00:33 UTC, Steven Schveighoffer wrote: I have a template function like this: ```d auto foo(T, Args...)(Args args) {...} ``` If I try to bind the T only, and produce a partial template function which can accept any number of parameters, but has T already specified, I get an error, because instantiating `foo!T` means Args is length 0. https://phobos.dpldocs.info/std.meta.ApplyLeft.html Should have read further--this does not work with template functions due to [issue 1807.][1] My mistake. [1]: https://issues.dlang.org/show_bug.cgi?id=1807 So first, I though ApplyLeft would work, but I convinced myself it was focused on applying the template to arguments individually, but that's just the example used. ApplyLeft is exactly what I'm looking for, but as you said (and as my example shows), it doesn't work in this case. It would be nice to have something that would work (or make ApplyLeft work via a compiler change). Thanks for the nudge! -Steve
equivalent of std.functional.partial for templates?
I have a template function like this: ```d auto foo(T, Args...)(Args args) {...} ``` If I try to bind the T only, and produce a partial template function which can accept any number of parameters, but has T already specified, I get an error, because instantiating `foo!T` means Args is length 0. I was surprised not to see something in std.meta that could create this for me. In `std.functional` there is `partial` (which bizarrely only allows one parameter to be specified), but I don't see an equivalent for template parameters. For functions, it seems IFTI can't see through to infer the template parameters of the alias, but you can have a function wrapper: ```d template bindFirst(alias F, Args...) { // this doesn't work // alias bindFirst(Args2...) = F!(Args, Args2); // but this does auto bindFirst(Args2...)(Args2 args2) { return F!(Args)(args2); } } alias bf = bindFirst!(foo, int); bf("hello", 5); // ok ``` It would be nice if the alias worked, but I don't know what's involved to make IFTI work there. I know I can alter foo to be a template within a template. Perhaps that's the right answer. However, this doesn't help for functions already written that I can't alter. Any ideas on how to solve this? I know my function solution is not very flexible... -Steve
Re: DUB "Error: only one `main` allowed."
On 8/11/21 5:31 AM, tastyminerals wrote: I would like to trigger tests in a simple dub project. ``` source/my_script.d dub.json ``` Here is a dub config: ```json { "targetPath": "build", "targetType": "executable", "sourcePaths": ["source"], "name": "my_script", "buildTypes": { "release": { "buildOptions": [ "releaseMode", "inline", "optimize" ] }, "tests": { "buildOptions": [ "unittests" ] } } } ``` The project builds but when I attempt to run `dub test`, I get ``` .dub/code/my_script-test-application-unittest-posix.osx.darwin-aarch64.arm_hardfloat-ldc_v1.26.0-8A5B544D5AC6B47B68DE875ACB4BA60E_dub_test_root.d(9,12): Error: only one `main` allowed. Previously found `main` at source/my_script.d(131,6) ``` How can one run tests with dub? `dub -b unittest` should work (you don't need the extra build type stuff) dub test does something funky -- it removes the *whole module* where your main function is (if you identify it, or if it's `app.d`) and then builds its own main module. Why does it do this? Legacy reasons, the runtime used to run main after running unittests, which dub didn't want to do. It also is useful on a library where there is no main function. However, dub with a build type of `unittest` just enables the unittest switch, and builds all your stuff as normal. -Steve
Re: How Add Local modules mymodule.d using DUB?
On 8/9/21 12:32 PM, Marcone wrote: My main program need import a local module called mymodule.d. How can I add this module using DUB? Thank you. You mean how to add a local project (that isn't on code.dlang.org)? `dub add-local .` inside the project directory. I don't think you can add a file directly without a project, but possibly. -Steve
Re: best/proper way to declare constants ?
On 8/5/21 11:09 AM, someone wrote: On Thursday, 5 August 2021 at 10:28:00 UTC, Steven Schveighoffer wrote: H.S. Teoh, I know you know better than this ;) None of this is necessary, you just need `rtValue` for both runtime and CTFE (and compile time parameters)! Now, the original question is about *associative arrays*, which are a different animal. Those, you actually have to initialize using a static constructor, and does indeed need both an enum and a static immutable, as CTFE currently does not understand runtime AAs. This is a huge issue since you do need silly things like the `if(__ctfe)` statement you wrote, and keep an enum handy for those cases which is identical to the static immutable. We really need to fix this. When you say "We really need to fix this" you mean that *eventually* associative-arrays will be available at compile-time ? I mean eventually AAs that are reasonably available at compile time, even though the structure is determined by the runtime, should be available at compile time. This allows them to be as usable with static immutable as regular arrays (and just about any other struct) are. Right now, AA's implementation is completely opaque via extern(C) function prototypes implemented in the runtime, so the compiler doesn't know how to make one. -Steve
Re: best/proper way to declare constants ?
On 8/4/21 11:20 PM, H. S. Teoh wrote: On Thu, Aug 05, 2021 at 01:39:42AM +, someone via Digitalmars-d-learn wrote: [...] What happens in the following case ? public immutable enum gudtLocations = [ r"BUE"d : structureLocation(r"arg"d, r"Buenos Aires"d, r"ART"d), r"GRU"d : structureLocation(r"bra"d, r"São Paulo"d, r"BRT"d), r"HHN"d : structureLocation(r"deu"d, r"Frankfurt am Main"d, r"CET"d), r"LHR"d : structureLocation(r"gbr"d, r"London"d, r"UTC"d), r"NYC"d : structureLocation(r"usa"d, r"New York"d, r"EST"d) ]; This is something that I also need at compilation time. [...] If you need a constant array value both at compile-time and runtime, one way to do it is to declare an enum that is used only by compile-time code, and the same enum is used once to declare the runtime static immutable. A static immutable *array* is usable at compile time. No need for the enum. Example: enum ctValue = [ "my", "data", "here", ... ]; // Initialize this once with ctValue. static immutable string[] rtValue = ctValue; if (ctfe) { `if(__ctfe) {` // Compile-time: use ctValue foreach (value; ctValue) { ... } } else { // Runtime: use rtValue instead foreach (value; rtValue) { ... } } Just be sure you don't use ctValue during runtime, otherwise it will incur an allocation per use. H.S. Teoh, I know you know better than this ;) None of this is necessary, you just need `rtValue` for both runtime and CTFE (and compile time parameters)! Now, the original question is about *associative arrays*, which are a different animal. Those, you actually have to initialize using a static constructor, and does indeed need both an enum and a static immutable, as CTFE currently does not understand runtime AAs. This is a huge issue since you do need silly things like the `if(__ctfe)` statement you wrote, and keep an enum handy for those cases which is identical to the static immutable. We really need to fix this. -Steve
Re: __FILE__
On 8/4/21 10:27 PM, Ali Çehreli wrote: I wonder whether this feature is thanks to 'lazy' parameters, which are actually delegates. No, the default parameters are used directly as if they were typed in at the call site (more or less, obviously the `__FILE__` example is weird). So: ```d writeln(foo()); ``` is just like you did: ```d writeln(foo(bar())); ``` There are no lazy parameters involved. -Steve
Re: best/proper way to declare constants ?
On 8/4/21 10:27 PM, someone wrote: On Thursday, 5 August 2021 at 02:06:13 UTC, Steven Schveighoffer wrote: On 8/4/21 9:14 PM, H. S. Teoh wrote: Unless you have a specific reason to, avoid using `enum` with string and array literals, because they will trigger a memory allocation *at every single reference to them*, which is probably not what you want. Just want to chime in and say this is NOT true for string literals. Only array literals. OK. Not for arrays then ... but for string literals ? which one then ? static immutable string fileName = "list.txt"; vs enum fileName = "list.txt"; The main difference between enums and static immutable is that the latter has an address at runtime. You cannot take the address of an enum (which only exists at compile time). You can think of an enum to be a substitute for typing out that expression directly. For array literals, this means, do a new allocation. However, a string literal is a special case of an array which does NOT allocate -- it puts the string data into the read-only segment, and the literal references that data, which is why string enums do not allocate when used. So the answer is, depends on what you are going to do with the data. There are use cases for both. If you just want an alias to represent the literal, I'd say use enum, it should work fine. Off the top of my head for strings: 1. A static immutable loses its "C string compatibility", whereas an enum does not. 2. A static immutable can be passed as an alias to a template, and the template mangle only involves the variable name, whereas passing an enum will use the string *contents* for the template mangle. This can be a huge difference for symbol sizes. 3. A static immutable can be used as an argument to a reference parameter, an enum cannot. 4. A static immutable will consume space in your executable even if never used, an enum will not. -Steve
Re: __FILE__
On 7/26/21 1:05 PM, Stefan Koch wrote: On Monday, 26 July 2021 at 12:01:23 UTC, Adam D Ruppe wrote: On Monday, 26 July 2021 at 11:43:56 UTC, workman wrote: __FILE__[0..$] Why do you have that [0..$] there? It is probably breaking the __FILE__ magic. Correct. The compiler has to evaluate the default argument as constant expression in order to use it as default value.. This is not true, you can use runtime calls as default values. Therefore it evaluates (__FILE__)[0 ..$]you first eval __FILE__ at CTFE within the module you are defining the function in. And then you slice it from zero to length. This might be how it is implemented, but it shouldn't be. `__FILE__` should be usable inside any expression as a default value, which should expand to the call-site for the function (as usual). But this has nothing to do with CTFE as far as I know. -Steve
Re: best/proper way to declare constants ?
On 8/4/21 9:14 PM, H. S. Teoh wrote: Unless you have a specific reason to, avoid using `enum` with string and array literals, because they will trigger a memory allocation *at every single reference to them*, which is probably not what you want. Just want to chime in and say this is NOT true for string literals. Only array literals. -Steve
Re: __traits() to get parameter details only ? ... hasMember looks up everything within
On 8/4/21 11:08 AM, someone wrote: However, __traits(hasMember, ...) checks for the existence of anything labeled lstrCurrencyID within the class (eg: unrelated variables with same name; not gonna happen, but, I like to code it the right way); so, question is: is there any way to search the parameter declarations only ? Have you looked at [std.traits](https://dlang.org/phobos/std_traits.html) at all? It does a lot of stuff, including giving you parameter names and types. -Steve
Re: Two major problems with dub
On 8/4/21 4:18 AM, evilrat wrote: On Wednesday, 4 August 2021 at 07:21:56 UTC, Denis Feklushkin wrote: On Sunday, 1 August 2021 at 17:37:01 UTC, evilrat wrote: vibe-d - probably because it handles DB connection and/or keep things async way, sure you probably can do it with Phobos but it will be much more PITA and less performant It is because Postgres provides JSON types Than again like I said it is library author mistake, if only JSON is ever used then it should depend on vibe-d:data specifically and not the whole vibe-d thing. He is the library author. And [that's exactly what he does](https://github.com/denizzzka/dpq2/blob/c1f1c7c26f7e6cac7a34778dc580c92d8dec013b/dub.json#L12). Note that when you depend on a subpackage, it downloads the entire repository (it has to), but will only build the subpackage. -Steve
Re: Two major problems with dub
On 8/1/21 11:38 AM, Alain De Vos wrote: Dub has two big problems. 1. Unmaintained dub stuff. 2. Let's say you need bindings to postgresql library and you will see dub pulling in numerous of libraries, which have nothing at all to do with postgresql. More like a framework stuff. This creates unneeded complexity, bloatware, dependency hell, maintainability, in my humble opinion. Dub should do one thing and do it good. Feel free to elaborate. My biggest pet peeve is when a library pulls in a unittest framework (which then might pull in all kinds of other things). I get it, and I get why it's needed as a non-optional dependency, but I have no intention on unittesting the library, I just want to use it. It's a shame to pull in everything that it needs because of that. I recently added the [dateparser](https://code.dlang.org/packages/dateparser) project as a library. I found it was pulling in emsi-container, so it could have an array container ([one line of code](https://github.com/JackStouffer/date-parser/blob/55e6218427974051b5179c98e0828b1d2a17629e/source/dateparser/package.d#L807)) that enables use of stdx.allocator. Ironically, the default (and all I cared about) is using the GC allocator. I wish there was a way to make this dependency optional. If more dub projects used optional dependencies, that would be nice. Given the way D works, and often template-heavy coding styles, I think it's going to be hard to do this correctly, without careful attention and lots of `version(has_xxx)` conditionals. -Steve
Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?
On 7/23/21 3:30 PM, apz28 wrote: On Friday, 23 July 2021 at 18:44:47 UTC, Steven Schveighoffer wrote: On 7/22/21 7:43 PM, apz28 wrote: In any case, it's possible that fbConnection being null does not mean a null dereference, but I'd have to see the class itself. I'm surprised if you don't get a null dereference in non-release mode, unless this code is never actually called. The -debug build with passing unit-tests so no problem there. The -release build is having problem. After make change to accommodate it, it takes forever to build. I started it yesterday 11AM and it is still compiling now (more than a day already.) It takes a full 100% core and peek memory usage is 2.2GB. The hard-drive is SSD That is a separate problem. That build is hung, and you likely have found a bug in the compiler. I have never seen a build last more than a few minutes at the most. If the code you posted is not crashing with a segfault, then it's possible there is a code generation issue. I still believe you have your check backwards. -Steve
Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?
On 7/22/21 7:43 PM, apz28 wrote: FbConnection is a class, FbXdrReader is a struct and for this call, response.data is not null & its' length will be greater than zero and FbConnection is not being used. So why DMD try to evaluate at compiled time hence error 1. Should not evaluate at compile time for this function call/construct 2. The error message is missing proper line # or nothing related to the module displayed in error message https://github.com/apz28/dlang/blob/main/source/pham/db/db_fbbuffer.d#L527 I have a feeling that line is backwards. It says: if the buffer has length, ignore it and use the connection, otherwise use the (empty) buffer data. So perhaps this is actually a real error that is being flagged (because it's inlined)? In any case, it's possible that fbConnection being null does not mean a null dereference, but I'd have to see the class itself. I'm surprised if you don't get a null dereference in non-release mode, unless this code is never actually called. -Steve
Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?
On 7/22/21 2:38 PM, apz28 wrote: On Wednesday, 21 July 2021 at 20:39:54 UTC, Dukc wrote: On Wednesday, 21 July 2021 at 14:15:51 UTC, Steven Schveighoffer wrote: 2. It's hard for me to see where the null dereference would be in that function (the `bool` implementation is pretty simple). DMD complains about dereferences in three different lines. I suspect it's `this` reference that is `null`. Look like DMD has some bug. If I changed this line https://github.com/apz28/dlang/blob/02989b94bfe306d723f2780e010c61f71f873cbe/source/pham/db/db_fbdatabase.d#L148 from: auto reader = FbXdrReader(null, response.data); to: auto reader = FbXdrReader(fbConnection, response.data); then the error go away. FbXdrReader constructor allows to accept null for that parameter. Is it "safe" means not allow to pass null? I don't know what an FbConnection is, but it looks like you call something on it. Your code is immense, and github search really *really* sucks. So I can't get better information. But if it's a class, and that is a normal member, it is indeed dereferencing a null pointer. -Steve
Re: associative array with Parallel
On 7/22/21 1:46 AM, seany wrote: Consider : int [] ii; foreach(i,dummy; parallel(somearray)) { ii ~= somefunc(dummy); } This is not safe, because all threads are accessing the same array and trying to add values and leading to collision. Correct. You must synchronize on ii. But : int [] ii; ii.length = somearray.length; foreach(i,dummy; parallel(somearray)) { ii[i] ~= somefunc(dummy); } This is safe. In this case, threads are accessing an unique memory location each. This isn't valid code, because you can't append to an integer. Though I think I know what you meant. Is it thread-safe (assuming the array elements are appendable)? I think so, but I'd have to see a working example. But what about this : int [ string ] ii; ii.length = somearray.length; foreach(i,dummy; parallel(somearray)) { string j = generateUniqueString(i); ii[j] ~= somefunc(dummy); } Is this also guaranteed thread safe? First, this also isn't valid code. You can't set the length of an AA. But I'm assuming that length setting is really a placeholder for initialization (in your real code). Also, again, you cannot append to an integer. Second, as long as you don't modify the AA *structure*, you can parallel with it. In this case, you are generating some string, and appending to that. I don't know what your `generateUniqueString` is doing, nor do I know what's actually stored as keys in the AA as your initialization code is hidden. If every `j` is guaranteed to already exist as a key in the AA, and the code is made to be valid, then I think it is thread-safe. If any access with a key `j` is inserting a new AA bucket, it is *not* thread-safe. However, this is a tall order, and highly depends on your code. The compiler cannot help you here. In my 5 runs, I did not see any problems, but I'd like to confirm. Thank you. Testing 5 times is not a substitute for proving the thread safety. I have learned one thing long ago about threads and race conditions. Just don't do it. Ever. Even if you test 1 times, and it doesn't fail, it will eventually. I've had code that hit a race condition after 2 weeks of running flat-out. Was one of the hardest things I ever had to debug. -Steve
Re: How to Fix Weird Build Failure with "-release" but OK with "-debug"?
On 7/21/21 7:56 AM, apz28 wrote: On Wednesday, 21 July 2021 at 11:52:39 UTC, apz28 wrote: On Wednesday, 21 July 2021 at 04:52:44 UTC, Mathias LANG wrote: It seems the compiler is doing extra analysis and seeing that a null pointer is being dereferenced. Can you provide the code for "pham\db\db_skdatabase.d" at L138 through 140 ? ```d package(pham.db): // Line# 133 final DbReadBuffer acquireSocketReadBuffer(size_t capacity = DbDefaultSize.socketReadBufferLength) nothrow @safe { version (TraceFunction) dgFunctionTrace(); if (_socketReadBuffer is null) _socketReadBuffer = createSocketReadBuffer(capacity); return _socketReadBuffer; } ``` The entire codes is available from github https://github.com/apz28/dlang/blob/main/source/pham/db/db_skdatabase.d#L138 1. That filename is totally wrong, or the function name is totally wrong. ddemangle says the function is `@safe bool[] pham.db.fbdatabase.FbArray.readArrayImpl!(bool).readArrayImpl(pham.db.database.DbNameColumn)` which seems to be located [here](https://github.com/apz28/dlang/blob/02989b94bfe306d723f2780e010c61f71f873cbe/source/pham/db/db_fbdatabase.d#L142) But the line numbers also don't match. maybe an inlining issue? 2. It's hard for me to see where the null dereference would be in that function (the `bool` implementation is pretty simple). -Steve
Re: betterC shared static ctor
On 7/21/21 5:07 AM, vit wrote: Thanks, it works, but now I have different problem. I need call static method for all instantions of template struct from `crt_constructor`. Is there way to iterate over all instantions of template? Not unless you register them somehow upon instantiation. Or (I think) you can implement the constructor as a static method, and tag it with `pragma(crt_constructor)`. Then it gets added when instantiated. -Steve
Re: How to parse a json node that contains children of different types?
On 7/20/21 11:00 PM, Mathias LANG wrote: But if you take a step back, I think you might find this solution is far from ideal. Having worked on a JSON library myself, I can tell you they are all implemented with a tagged union. And converting a tagged union to a tagged union is no improvement. Not [jsoniopipe](https://github.com/schveiguy/jsoniopipe). In that case, you could use a specialized type with a `fromJSON` static member to do whatever you wanted. -Steve
Re: Yet another parallel foreach + continue question
On 7/19/21 10:58 PM, H. S. Teoh wrote: I didn't check the implementation to verify this, but I'm pretty sure `break`, `continue`, etc., in the parallel foreach body does not change which iteration gets run or not. `break` should be undefined behavior (it is impossible to know which loops have already executed by that point). `continue` should be fine. Noted in the [docs](https://dlang.org/phobos/std_parallelism.html#.TaskPool.parallel): Breaking from a parallel foreach loop via a break, labeled break, labeled continue, return or goto statement throws a ParallelForeachError. I would say `continue` is ok (probably just implemented as an early return), but all those others are going to throw an error (unrecoverable). -Steve
Re: How to create friends of a class at compile time?
On 7/15/21 1:43 PM, Tejas wrote: How do you write the equivalent of that in D? Is the answer still the same? Manually keep it in the same module, or is there a programmatic way of converting this to D? Functions in the same module can access `private` members. Functions in the same package (or in whatever package you specify) can access `package` members. That is how D does "friends". So the answer to your question depends on how the C++ code is organized. It's always possible that something in C++ here is not translatable into D, but most likely can be redesigned (and likely better designed). -Steve
Re: Manipulate and parse jasonb object in timescaledb(postgresql)
On 7/14/21 9:00 AM, Alain De Vos wrote: When I read a record out of the database I receive a jsonb datatatype as a string. How do I convert this string into a json object and parse and manipulate it? Isn't jsonb just a storage assumption for the database (so it can do efficient indexing/searches)? When you get the data back, I would think it's just json data you can parse. I don't have experience with it, but I can't imagine a portable psql library that actually implements whatever binary storage format is being used inside the DB. -Steve
Re: Can I get the time "Duration" in "nsecs" acurracy?
On 7/9/21 5:13 PM, rempas wrote: On Friday, 9 July 2021 at 20:54:21 UTC, Paul Backus wrote: On Friday, 9 July 2021 at 20:43:48 UTC, rempas wrote: I'm reading the library reference for [core.time](https://dlang.org/phobos/core_time.html#Duration) and It says that the duration is taken in "hnsecs" and I cannot understand if we can change that and choose the precision. Does anyone know if we can do that? It is stored internally in "hnsecs", but you can convert it to other units using the `total` method [1]; for example, `myDuration.total!"nsecs"`. [1] https://dlang.org/phobos/core_time.html#.Duration.total It doesn't work for me. I have the following code: ``` MonoTime start = MonoTime.currTime(); // Doing stuff MonoTime end = MonoTime.currTime(); Duration dur = end - start; dur = dur.total!"nsecs"; ``` and I get the following error message: "Error: cannot implicitly convert expression \`dur.total()\` of type \`long\` to \`Duration`" BTW `Duration` is truncating here. `MonoTime` stores its values in implementation-defined ticks, which can be nanoseconds or any other thing that the specific clock uses. Whereas `Duration` uses strictly hnsecs. If you want to get sub-hnsec resolution, use the `ticks` member of `MonoTime` and `ticksPerSecond` and do the math for the units. See the warning [here](https://dlang.org/phobos/core_time.html#.MonoTimeImpl.opBinary). -Steve
Re: mixin template's alias parameter ... ignored ?
On 7/11/21 8:49 AM, Adam D Ruppe wrote: On Sunday, 11 July 2021 at 05:20:49 UTC, someone wrote: ```d mixin template templateUGC ( typeStringUTF, alias lstrStructureID ) { public struct lstrStructureID { typeStringUTF whatever; } This creates a struct with teh literal name `lstrStructureID`. Just like any other name. So it is NOT the value of the variable. ```d public struct mixin(lstrStructureID) { ... } ``` because the argument seems to require a complete statement. Indeed, you'd have to mixin the whole thing like mixin("public struct " ~ lstrStructureId ~ " { ... } "); when I've done this kind of stuff, what I usually do is: ```d struct Thing { ... // actual struct } mixin("alias ", lstrStructureID, " = Thing;"); ``` the downside is that the actual struct name symbol will be `Thing`, or whatever you called it. But at least you are not writing lots of code using mixins. -Steve
Re: assert(false) and GC
On 7/10/21 12:32 PM, Mathias LANG wrote: On Saturday, 10 July 2021 at 01:38:06 UTC, russhy wrote: On Saturday, 10 July 2021 at 01:23:26 UTC, Steven Schveighoffer wrote: I think it's the throwing/catching of the `Throwable` that is allocating. But I don't know from where the allocation happens. i think you are right Try to use `@nogc` instead, it'll show you it does not allocate. A caveat though: A failing assert used to allocate before v2.097.0 (the latest version), it does not anymore. However, as your test captures all GC allocation, it likely triggers while the runtime is initializing. No, because if you remove the assert, and just include the override of gc functions, nothing triggers. I can't remember which release, but the runtime has been changed to not use the GC until the application needs it. The assert is triggering the GC, either on the throw or the catch (i.e. printing out the stack trace). I tend to think the latter, but hard to prove with this simple test. If you want to know where it is, just debug it and break in the GC allocation function. -Steve
Re: assert(false) and GC
On 7/9/21 8:44 PM, russhy wrote: On Friday, 9 July 2021 at 23:34:25 UTC, Ali Çehreli wrote: On 7/9/21 4:12 PM, russhy wrote: >> One way of forcing compile-time evaluation in D is to define an enum >> (which means "manifest constant" in that use). That's all I meant. It was a general comment. > this is very bad, assert are good because they are one liner, making it > 2 line to avoid GC is just poor design, compiler should be smarter There must be a misunderstanding. The one-liner does not allocate either (or @nogc is broken). https://run.dlang.io/is/HJVSo0 it allocates That test is possibly showing the wrong thing. You are capturing all allocations, not just the concatenation. Change the assert line to: ```d string s = __FUNCTION__ ~ "This is an error message"; ``` And no GC allocations occur. Even without optimizations turned on. I think it's the throwing/catching of the `Throwable` that is allocating. But I don't know from where the allocation happens. -Steve
Re: Can I get the time "Duration" in "nsecs" acurracy?
On 7/9/21 5:04 PM, Ali Çehreli wrote: On 7/9/21 1:54 PM, Paul Backus wrote: On Friday, 9 July 2021 at 20:43:48 UTC, rempas wrote: I'm reading the library reference for [core.time](https://dlang.org/phobos/core_time.html#Duration) and It says that the duration is taken in "hnsecs" and I cannot understand if we can change that and choose the precision. Does anyone know if we can do that? It is stored internally in "hnsecs", but you can convert it to other units using the `total` method [1]; for example, `myDuration.total!"nsecs"`. [1] https://dlang.org/phobos/core_time.html#.Duration.total Yes but the resolution seems not to be better than 100 nsecs. A quick research reveals a better resolution is not possible with common hardware on at least Linux. The following program always prints multiples of 100 on my Mint OS: import std.stdio; import core.thread; import std.datetime.stopwatch; void main() { auto sw = StopWatch(); sw.start(); foreach (_; 0..10) { Thread.sleep(0.nsecs); writefln("%,s", sw.peek.total!"nsecs"); } } You can get better than hnsecs resolution with `core.time.MonoTime`, which can support whatever the OS supports. However, `Duration` and `SysTime` are stored in hnsecs for a very specific reason -- range. Simply put, if you have a 64-bit integer, and you picked nanoseconds as the unit, you can store only 585 years of range. 10 ns gives you 5850 years, and 100 ns gives you 58k years. That should be good enough for all but the most esoteric calculations (given that a `Duration` is signed, this gives a range of roughly -29k years to 29k years). Note also that hnsecs is the base unit for Windows high precision clocks, though their epoch is year 1600 instead of year 0. -Steve
Re: Where is "open" in "core.sys.linux.unistd"?
On 7/9/21 11:31 AM, Dennis wrote: On Friday, 9 July 2021 at 15:11:38 UTC, Steven Schveighoffer wrote: But reading/writing, closing these file descriptors is always the same. For sockets you'd typically use `recv` and `send` instead or `read` and `write` because the former give extra options and the latter don't work on Windows. But yeah, on Linux `read` and `write` should work universally among file descriptors. I typically only use `send` and `recv` for for connectionless sockets. For TCP sockets, it's generally `read` and `write` for me (and it works fine). Windows is a different story, they have different i/o routines for system calls (yes, there's the shims for Posix file descriptors, but I wouldn't use those anyway). The larger point is that the reason `read`/`write` are separate from descriptor creation is because they are universal, while creation is not. -Steve
Re: Where is "open" in "core.sys.linux.unistd"?
On 7/9/21 10:51 AM, rempas wrote: The file can be found quickly [here](https://github.com/dlang/druntime/blob/master/src/core/sys/posix/unistd.d) or in your system if you want. Now the question is, why isn't there an "open" function for the equivalent system call? "close", "write", "read" etc. all exist. Anyone knows what's going on with open? Because file descriptors are created in different ways. For example, `open` exists for files [here](https://github.com/dlang/druntime/blob/master/src/core/sys/posix/fcntl.d) But opening a socket is done via the `socket` system call [here](https://github.com/dlang/druntime/blob/master/src/core/sys/posix/sys/socket.d) They don't take the same arguments (nor should they). But reading/writing, closing these file descriptors is always the same. -Steve
Re: to compose or hack?
On 7/7/21 3:52 PM, Sebastiaan Koppe wrote: On Wednesday, 7 July 2021 at 13:30:28 UTC, Steven Schveighoffer wrote: On 7/7/21 5:54 AM, rassoc wrote: On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote: So I have this situation where I need to split a string, then where the splits are, insert a string to go between the elements making a new range, all without allocating (hopefully). Without considering the more general case, isn't that just splitter-joiner? No, splitter-joiner would make a range of characters, I want a range of strings. Just lift each item in a range then: ```d import std; auto foo(string s, string sp, string j) @nogc { return s.splitter(sp).map!(i => only(i)).joiner(only(j)); } void main() { foo("ab,cd,ef,gh", ",", "##").writeln; // => ["ab", "##", "cd", "##", "ef", "##", "gh"] } ``` Thanks! This is exactly what I was reaching for. `only` is one of the coolest functions (I use it elsewhere too). -Steve
Re: to compose or hack?
On 7/7/21 5:54 AM, rassoc wrote: On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote: So I have this situation where I need to split a string, then where the splits are, insert a string to go between the elements making a new range, all without allocating (hopefully). Without considering the more general case, isn't that just splitter-joiner? No, splitter-joiner would make a range of characters, I want a range of strings. ```d import std; auto foo(string s, string sp, string j) @nogc { return s.splitter(sp).joiner(j); } void main() { foo("ab,cd,ef,gh", ",", "##").writeln; // => ab##cd##ef##gh } ``` Using your example, the correct result should be `["ab", "##", "cd", "##", "ef", "##", "gh"]` Interesting! Tried it myself, shame that this doesn't quite work: ```d import std; auto foo(R)(string s, string sp, R r) @nogc { return s.splitter(sp).zip(r) .map!(a => a.expand.only) .joiner.dropBackOne.joiner; // not bidirectional } void main() { foo("ab,cd,ef,gh", ",", ["##", "**"].cycle).writeln; } ``` ooh, I like the zip/expand/only trick! I got this to work, and lol, I don't think I'd ever use this: ```d auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U == ElementType!R)) { return zip(StoppingPolicy.shortest, src, middles.repeat) .map!(e => only(e.expand)) .joiner .slide(2) .frontTransversal; } ``` Ironically, I think it would still run the splitting algorithm 2x, because `slide` has to store 2 copies of the source range. And it's not nogc either. Hm... I bet `dropBackOne` might actually be able to work on a forward range if it cached one element? But that might be iffy. -Steve
Re: to compose or hack?
On 7/6/21 11:42 PM, Jon Degenhardt wrote: On Wednesday, 7 July 2021 at 01:44:20 UTC, Steven Schveighoffer wrote: This is pretty minimal, but does what I want it to do. Is it ready for inclusion in Phobos? Not by a longshot! A truly generic interleave would properly forward everything else that the range supports (like `length`, `save`, etc). But it got me thinking, how often do people roll their own vs. trying to compose using existing Phobos nuggets? I found this pretty satisfying, even if I didn't test it to death and maybe I use it only in one place. Do you find it difficult to use Phobos in a lot of situations to compose your specialized ranges? I try to compose using existing Phobos facilities, but don't hesitate to write my own ranges. The reasons are usually along the lines you describe. For one, range creation is easy in D, consistent with the pro/con tradeoffs described in the thread/talk [Iterator and Ranges: Comparing C++ to D to Rust](https://forum.dlang.org/thread/diexjstekiyzgxlic...@forum.dlang.org). Another is that if application/task specific logic is involved, it is often simpler/faster to just incorporate it into the range rather than figure out how to factor it out of the more general range. Especially if the range is not going to be used much. Yeah, I agree with all this. I do try to use existing ranges/algorithms as much as possible. But I find it awesome you can just whip up a quick shim range to get work done and not worry about making it perfect for general consumption. Kind of like a lambda range ;) -Steve
to compose or hack?
So I have this situation where I need to split a string, then where the splits are, insert a string to go between the elements making a new range, all without allocating (hopefully). Looking around phobos I found inside the documentation of [roundRobin](https://dlang.org/phobos/std_range.html#.roundRobin) something that does *exactly* what I'm looking for. Except... the provided `interleave` function iterates the original range twice, which means 2x the searching calls for splitter. Why does it do this? Because `roundRobin` will keep going as long as ANY range still has data left, so you need to make the "interleaving" range stop when the first one stops. After struggling to think up ways to compose this (hm.., can I make the ranges share a stopping point?) without the 2x penalty, I just decided to write my own interleave range which does exactly what I am looking for: ```d auto interleave(R, U)(R src, U middles) if (isInputRange!R && is(U == ElementType!R)) { static struct Result { R src; U middles; bool between = false; auto front() { assert(!empty); return between ? middles : src.front; } void popFront() { assert(!empty); if(between) between = false; else { src.popFront; between = true; } } bool empty() { return src.empty; } } return Result(src, middles); } ``` This is pretty minimal, but does what I want it to do. Is it ready for inclusion in Phobos? Not by a longshot! A truly generic interleave would properly forward everything else that the range supports (like `length`, `save`, etc). But it got me thinking, how often do people roll their own vs. trying to compose using existing Phobos nuggets? I found this pretty satisfying, even if I didn't test it to death and maybe I use it only in one place. Do you find it difficult to use Phobos in a lot of situations to compose your specialized ranges? Oh, and if you do know of a better way to compose the range that doesn't require the double iteration, I'd be interested in seeing it. -Steve
Re: How to disable assigning a value to a property?
On 7/6/21 9:27 AM, Jack Applegame wrote: On Tuesday, 6 July 2021 at 12:33:20 UTC, Adam D Ruppe wrote: The language always allows `a = b;` to be rewritten as `a(b);`. And that's sad. It should happen for properties only. Yes, I lament that there is no way to control how people call your function. It can result in surprising things, and it means as a library designer you have to consider this usage when picking names. There are a few "draft" DIP proposals (under the old DIP system) here: https://wiki.dlang.org/DIPs But I think the time of being able to make such a disruptive change has passed. For better or worse we have the half-implemented near-useless meaning of `@property`, and basically it's unneeded. -Steve
Re: anonymous functions and scope(exit)
On 7/3/21 4:08 PM, frame wrote: On Saturday, 3 July 2021 at 17:39:18 UTC, Steven Schveighoffer wrote: But in practice, the compiler does not have to clean up anything when an `Error` is thrown. Whether it does or not is defined by the implementation. This should be really mentionend in the docs? "Guard", yeah... Yeah, there isn't a good discussion of the differences between Error and Exception on that page. -Steve
Re: anonymous functions and scope(exit)
On 7/3/21 1:20 PM, Luis wrote: This is intentional ? ``` should(function void() { auto emptyStack = SimpleStack!int(); scope(exit) emptyStack.free; // <= This is never called emptyStack.reserve(16); emptyStack.top; }).Throw!RangeError; ``` scope(exit) inside of a anonymous functions, it's never called. In principle, it should technically be called. But in practice, the compiler does not have to clean up anything when an `Error` is thrown. Whether it does or not is defined by the implementation. However, it should *always* work if it's an `Exception` and not an `Error`. ```d import std.stdio; void main() { auto f = function void() { scope(exit) writeln("hi"); throw new Exception("boo"); }; f(); } ``` prints "hi" -Steve
Re: how much "real-life" code can be marked @safe ?
On 7/1/21 8:26 PM, someone wrote: ... just wondering: I am writing pretty trivial code, nothing out of the ordinary, and attempted to check how much of it could be marked safe ... It should be quite a bit. - Lots of tiny common library functions are pretty easy - Getter/Setter properties are easy too - almost all this() constructors are a no-go providing you do something in-between with the parameters until you assign them back to the target variables; eg: you have a char parameter (that you need to do something with it) that needs to be assigned to a class/structure string member variable and then it needs a cast ... but no castings are allowed with @safe This doesn't make a lot of sense, lots of constructors are safe. And casting is OK as long as it's safe, including class downcasts. But when you start attempting to declare @safe chunks of code that actually DO things ... well, it seems end-of-the-story. This is why you encapsulate the unsafe parts in @trusted functions. The classic example is the posix `read` and `write` functions. The function `int read(int fd, void *data, int len)` is not safe, nor can it be trusted. But a trusted wrapper is possible: `@trusted int readSafe(int fd, ubyte[] data)`. Now all of a sudden, safe functions have more utility. Declaring @safe void() main() {...} as I was advised in some previous post (to avoid declaring @safe everywhere) is almost impossible unless you are doing the hello world app. The point is to mark main @safe, and then fix whatever things that aren't safe that it calls to provide a safe interface. I would love to hear how you, I mean the community, approach code safeness ? Any function I want to make safe, I mark it as @safe. Then I fix the compiler complaints until it compiles (including functions that it calls), using as little @trusted code as possible. -Steve
Re: Printing Tuple!(...)[] using for loop?
On 7/2/21 12:21 AM, Kirill wrote: I have a `Tuple!(string, ..., string)[] data` that I would like to print out: `a b c` `1 2 3` `4 5 6` Furthermore, I want to be able to print any N rows and M columns of that table. For instance: `b c` `2 3` or `1 2 3` `4 5 6` I am using for loops for that: // inside some function(rows, cols): immutable startFromRow = ...; immutable endWithRow = ...; immutable startFromCol = ...; immutable endWithCol = ...; // print data for(size_t i = startFromRow; i < endWithRow; i++) { for(size_t j = startFromCol; j < endWithCol; j++) { writef("%s", data[i][j]); } writef("\n"); } And the compiler puts out the following: `Error: variable 'j' cannot be read at compile time` I tried `data[i].expand[j]`, but the same error occurs anyway. I have two questions: 1. How do I print the contents of a Tuple using for loops? Or any other method? 2. What am I missing? How does it actually work under the hood? So a tuple is really like an unnamed group of variables. A `Tuple!(int, int, int)` is really like three ints that are all separate variables. It's just that they are named via the group. It is NOT like an array, it's more like a struct with fields that have indexes instead of names. In order to print them in a loop, based on *runtime* data, you need to bridge the gap between runtime and compile time. Why? Because a Tuple does not necessarily contain the same types for every value, so `tup[0]` might have a different type than `tup[1]`. Because D is strongly-typed, you need to access these with *compile-time* indexes, so it knows what type you are using. Imagine you have a struct, and you want to use a runtime string to access a given field. This is essentially the same, except it's an index and not a name. A typical way to bridge the gap is to use a switch to validate the runtime variable, and then use the compile-time equivalalent to actually get the data. For example, you could write a function like: ```d void printItem(Tuple!(...) vals, size_t index) { theswitch: final switch(index) { static foreach(ctIdx; 0 .. vals.length) { case ctIdx: writeln(vals[ctIdx]); break theswitch; } } } ``` Now, if you want to just print them in order, without any runtime details, you can just use foreach on a tuple and it works (the foreach variables are compile-time determined). -Steve
Re: SegFault trying to chunk lazily joined ranges
On 7/1/21 10:56 AM, Keivan Shah wrote: Using the handler I was able to get the stack trace and it seems that the segFault is caused by `joiner` trying to call `.save` on a null object leading to a `NullPointerError`. But I have not been able to debug it further. Mostly it seems that there is something wrong with my understanding of ranges or it could be a genuine bug in std.range. Can anyone help me debug this piece of code? Thanks for the detailed instructions, very easy to reproduce. However, chunkBy is a hot mess, which probably has a bug in it somewhere. I don't exactly know where this is, but know that using objects for forward ranges is bound to result in some failures, simply because they are one of the only forward ranges that *requires* calling `.save`, and much code exists that forgets to do that. I spent about 20 minutes trying to find this and can't see how `chunkBy` actually works in this case. I don't have any more time to spend on it, sorry. I narrowed your code down to the minimal case that I could find that segfaults: ```d ForwardRange!int[] listOfRanges = [iota(1).inputRangeObject]; auto lazyFlattenedRange = joiner(listOfRanges); auto d2 = lazyFlattenedRange.chunkBy!(a => a); while(!d2.empty) d2.popFront; ``` I hope this helps someone narrow it down. -Steve
Re: How to reset the website when the user leaves it, with vibe.d?
On 6/29/21 4:25 PM, vnr wrote: Nevertheless, the problem persists and seems to be even deeper, indeed, my site is hosted on Heroku and I can see what a user who is on another machine has written (behavior I just found out). Fortunately, this little site is only for entertainment purposes, but it is a behavior that seems quite vicious. If you want to access the code, it is on [this repository](https://github.com/noc-lang/playground) (it is just a playground for the language of a friend). Has nothing to do with sessions, you are saving the text posted, and then making it the default text whenever the page is rendered. [here](https://github.com/noc-lang/playground/blob/0ec136b385c9aff306e15947082210d3bc230d10/source/app.d#L68) is where you save the text. [here](https://github.com/noc-lang/playground/blob/0ec136b385c9aff306e15947082210d3bc230d10/source/app.d#L50-L52) you pass it to the template, and [here](https://github.com/noc-lang/playground/blob/d6551e8a5f90b8ebc1732c6dfb72ba61113887af/views/home.dt#L128) you render it as the child of the text area. Just don't do that ;) -Steve
Re: Wrap + add methods?
On 6/28/21 11:53 AM, Paul Backus wrote: On Monday, 28 June 2021 at 15:17:34 UTC, Steven Schveighoffer wrote: I have a situation where I want to wrap a certain type to add a few methods to that type. UFCS is not an option, because the library that will use this type will not import the UFCS methods. `std.typecons.Proxy` doesn't seem to wrap static methods, and besides, I want to return wrappers if the function being wrapped returns the same type (this is critical for stuff like `auto result = a + b`, I want the result to be the same wrapped type). Are there any libraries that might do this (including Phobos)? https://code.dlang.org/packages/addle Doesn't do everything you're looking for, but you might find some useful tricks in the source. Very neat! I think I can't use it, because I need to add static methods. My particular use case is a translated database type. In this case, it's a fixed point currency, which is stored as an integer in the database, but translated to a D fixedpoint type. To make it work with my DB library, I need to have a method `dbValue` which converts the D type into an appropriate D type that the database can utilize (long in this case), and a static method `fromDBValue` which goes the opposite direction. For now, I've just hand implemented the needed functions. This includes forwarding constructors, operator overloads, opAssign, etc. -Steve
Wrap + add methods?
I have a situation where I want to wrap a certain type to add a few methods to that type. UFCS is not an option, because the library that will use this type will not import the UFCS methods. `std.typecons.Proxy` doesn't seem to wrap static methods, and besides, I want to return wrappers if the function being wrapped returns the same type (this is critical for stuff like `auto result = a + b`, I want the result to be the same wrapped type). Are there any libraries that might do this (including Phobos)? -Steve
Re: is it possible to sort a float range ?
On 6/23/21 7:07 PM, someone wrote: On Wednesday, 23 June 2021 at 22:46:28 UTC, Steven Schveighoffer wrote: Use the `release` method: ```d return lnumRange.sort!(...).release; ``` Fantastic, issue solved, I previously used sort ascending even descending but first time on floats. So I went and searched phobos docs: auto release(); Releases the controlled range and returns it. Not much clarification there. Can you elaborate a bit if possible Steve ? I think the purpose behind it is to say "here, now you have the original range back, so I won't guarantee it's sorted any more." I'm pretty sure it also clears out the source range in the sorted range, so you can no longer use the sortedness functions, but that's easily circumvented using `save`. I can't really defend the purpose/implementation of `SortedRange`, it's something in Phobos that I've complained about extensively in the past. -Steve
Re: Detect if a struct is a 3-float vector
On 6/23/21 6:36 PM, JN wrote: I'm looking for a way to test a struct for these conditions: 1. has members named x, y and z 2. these members are floating point type This works, but feels kinda verbose, is there some shorter way? Can I somehow avoid the hasMember/getMember calls? ```d import std.traits; struct Vector3f { float x, y, z; } struct Vector2f { float x, y; } struct Vector3i { int x, y, z; } bool isVector3fType(T)() { static if (__traits(hasMember, T, "x") && __traits(hasMember, T, "y") && __traits(hasMember, T, "z")) { static if (isFloatingPoint!(typeof(__traits(getMember, T, "x"))) && isFloatingPoint!(typeof(__traits(getMember, T, "y")))&& isFloatingPoint!(typeof(__traits(getMember, T, "z" { return true; } } return false; } void main() { static assert(isVector3fType!Vector3f); static assert(!isVector3fType!Vector2f); static assert(!isVector3fType!Vector3i); } ``` Hm.. what about: ```d enum isVector3fType(T) = FieldNameTuple!T.length == 3 && FieldNameTuple!T == AliasSeq!("x", "y", "z") && allSatisfy!(isFloatingPoint, Fields!T); ``` (the length thing was required, otherwise the thing complained for Vector2f) -Steve
Re: is it possible to sort a float range ?
On 6/23/21 6:30 PM, Jordan Wilson wrote: On Wednesday, 23 June 2021 at 19:53:24 UTC, someone wrote: Please, look for the line marked +++ This is a structure with a public property returning a (still unsorted) range built on-the-fly from already-set properties, a basic range from a to z with n step where some specific values can be added in-between. The range is a float which I am currently using for currency (horrible) and later plan to move it to decimal 10 or the like. [...] ```sort``` returns a ```SortedRange```, and I believe you wish to return a float. So you can do either ```return lnumRange.sort!(...).array;```, or you can do ```lnumRange.sort!(...); return lnumRange```. Use the `release` method: ```d return lnumRange.sort!(...).release; ``` -Steve
Re: how to filter associative arrays with foreach ?
On 6/21/21 5:00 PM, Elronnd wrote: On Monday, 21 June 2021 at 03:59:10 UTC, someone wrote: Is there a way to filter the collection at the foreach-level to avoid the inner if ? Here's how I would do it: foreach (k, v; coll) { if (k == unwanted) continue; ... } You still have an if, but the actual loop body doesn't have to be nested, so it's easy to follow the control flow. Alternatively (if you're ok with this sort of thing): foreach (k, v; coll) if (k != unwanted) { } It's actually visually shorter than doing the filter. And the benefit to using the if statement over the filter wrapper is that the compiler has to do a lot less work. -Steve