Re: Socket and spawn()
On Friday, May 31, 2024 10:07:23 AM MDT Andy Valencia via Digitalmars-d-learn wrote: > I'm coding a server which takes TCP connections. I end up in the > main thread with .accept() which hands me a Socket. I'd like to > hand this off to a spawn()'ed thread to do the actual work. > > Aliases to mutable thread-local data not allowed. > > Is there some standard way to get something which _isn't_ in TLS? > Or do I have to drop back to file descriptors and do my own > socket handling? > > TIA, > Andy Strictly speaking, unless you're dealing with a module or static-level variable, the object is not in TLS. It's treated as thread-local by the type system, and the type system will assume that no other thread has access to it, but you can freely cast it to shared or immutable and pass it across threads. It's just that it's up to you to make sure that you don't have a thread-local reference to shared data that isn't protected in a fashion that accessing the thread-local references is guarantee to be thread-safe (e.g. the appropriate mutex has been locked). So, if you're just passing it to another thread, and that other thread is all that uses the object, then you would temporarily cast it to shared or immutable, give it to the other thread, and then that thread would cast it back to thread-local to use it, and the original thread would have nothing to do with it any longer. On the other hand, if you're actively sharing an object across threads, then you cast it to shared and give it to the other thread. But then you have to use an appropriate thread-synchronization mechanism (likely a mutex in the case of a socket) to ensure that accessing the object is thread-safe. So, typically, you would lock a mutex to ensure that no other thread is accessing the object, and then you temporarily cast away shared while the object is protected by the mutex so that you can do whatever you need to do with the object, and once you're ready to release the mutex, you make sure that no thread-local references to the object remain before releasing the mutex. So, any code actually operating on the object would do so while it's typed as thread-local, and the compiler would complain if you accidentally accessed it through the shared referenc to the data (though the compiler doesn't currently catch all such cases - the -preview=nosharedaccess switch turns on more of the checks, and that's supposed to be become the default eventually, but it hasn't yet). In any case, you can freely cast between thread-local and shared. It's just that you need to be sure that when you do that, you're not violating the type system by having a thread-local reference to shared data access that shared data without first protecting it with a mutex. And that typically means not having any thread-local references to the shared data except when the mutex is locked. But if all you're doing is passing an object across threads, then it's pretty straightforward, since you just cast it to shared or immutable to be able to pass it across threads and then cast back to thread-local on the other side to use it as normal again (you just need to make sure that you don't leave a reference to the data on the original thread when you do that). - Jonathan M Davis
Socket and spawn()
I'm coding a server which takes TCP connections. I end up in the main thread with .accept() which hands me a Socket. I'd like to hand this off to a spawn()'ed thread to do the actual work. Aliases to mutable thread-local data not allowed. Is there some standard way to get something which _isn't_ in TLS? Or do I have to drop back to file descriptors and do my own socket handling? TIA, Andy
Re: need help to use C++ callback from garnet
On Wednesday, 29 May 2024 at 07:47:01 UTC, Dakota wrote: I try use https://github.com/microsoft/garnet/blob/main/libs/storage/Tsavorite/cc/src/device/native_device_wrapper.cc from D Not sure how to make this work with D: ```c++ EXPORTED_SYMBOL FASTER::core::Status NativeDevice_ReadAsync(NativeDevice* device, uint64_t source, void* dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->ReadAsync(source, dest, length, callback, context); } EXPORTED_SYMBOL FASTER::core::Status NativeDevice_WriteAsync(NativeDevice* device, const void* source, uint64_t dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->WriteAsync(source, dest, length, callback, context); } ``` I need to define `FASTER::core::AsyncIOCallback callback` from D, any way to workaround ? (like modify garnet source code to support pass a C function callback) I am newbie to C++ and D, any help will be appreciate (here is the signature of callback) https://github.com/microsoft/garnet/blob/ade2991f3737b9b5e3151d0dd0b614adfd4bcecd/libs/storage/Tsavorite/cc/src/device/async.h#L25 ```cpp typedef void(*AsyncIOCallback)(IAsyncContext* context, Status result, size_t bytes_transferred); ``` This can be written as following to match namespace and mangling scheme, assuming IAsyncContext is opaque pointer here, though I don't remember if enum need namespace as well. But no guarantess anyways, try it and adapt it. Also I can't remember if string list makes proper namespace or you should put `FASTER.core` instead (without quotes). ```d enum Status : ubyte { Ok = 0, Pending = 1, NotFound = 2, OutOfMemory = 3, IOError = 4, Corruption = 5, Aborted = 6, } extern(C++, "FASTER", "core") class IAsyncContext; alias AsyncIOCallback = extern(C++, "FASTER", "core") void function(IAsyncContext context, Status result, size_t bytes_transferred); ```
need help to use C++ callback from garnet
I try use https://github.com/microsoft/garnet/blob/main/libs/storage/Tsavorite/cc/src/device/native_device_wrapper.cc from D Not sure how to make this work with D: ```c++ EXPORTED_SYMBOL FASTER::core::Status NativeDevice_ReadAsync(NativeDevice* device, uint64_t source, void* dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->ReadAsync(source, dest, length, callback, context); } EXPORTED_SYMBOL FASTER::core::Status NativeDevice_WriteAsync(NativeDevice* device, const void* source, uint64_t dest, uint32_t length, FASTER::core::AsyncIOCallback callback, void* context) { return device->WriteAsync(source, dest, length, callback, context); } ``` I need to define `FASTER::core::AsyncIOCallback callback` from D, any way to workaround ? (like modify garnet source code to support pass a C function callback) I am newbie to C++ and D, any help will be appreciate
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 23:18:46 UTC, Steven Schveighoffer wrote: On Tuesday, 28 May 2024 at 18:41:02 UTC, bauss wrote: On Tuesday, 28 May 2024 at 18:29:17 UTC, Ferhat Kurtulmuş wrote: On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); You can do `SysTime(unixTimeToStdTime(0))` to get a SysTime that is at the unix epoch. Also figured out the second question based on your result. Simply doing: ``` SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milliseconds) ``` Seems to work. Note there is an `msecs` function: ```d SysTime(unixTimeToStdTime(0)) + milliseconds.msecs; ``` https://dlang.org/phobos/std_datetime_systime.html#unixTimeToStdTime https://dlang.org/phobos/core_time.html#msecs -Steve Thanks! That's a lot cleaner
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 18:41:02 UTC, bauss wrote: On Tuesday, 28 May 2024 at 18:29:17 UTC, Ferhat Kurtulmuş wrote: On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); You can do `SysTime(unixTimeToStdTime(0))` to get a SysTime that is at the unix epoch. Also figured out the second question based on your result. Simply doing: ``` SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milliseconds) ``` Seems to work. Note there is an `msecs` function: ```d SysTime(unixTimeToStdTime(0)) + milliseconds.msecs; ``` https://dlang.org/phobos/std_datetime_systime.html#unixTimeToStdTime https://dlang.org/phobos/core_time.html#msecs -Steve
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 18:29:17 UTC, Ferhat Kurtulmuş wrote: On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); // Get the total milliseconds long milliseconds = unixTime.total!"msecs"; // Print the Unix time in milliseconds writeln("Unix time in milliseconds: ", milliseconds); } Thanks a lot. Also figured out the second question based on your result. Simply doing: ``` SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milliseconds) ``` Seems to work.
Re: Get milliseconds from time and construct time based on milliseconds
On Tuesday, 28 May 2024 at 17:37:42 UTC, bauss wrote: I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks Unixtime might be what you want: import std; import std.datetime; import std.stdio; void main() { // Get the current time in the UTC time zone auto currentTime = Clock.currTime(); // Convert the time to the Unix epoch (1970-01-01T00:00:00Z) Duration unixTime = currentTime - SysTime(DateTime(1970, 1, 1), UTC()); // Get the total milliseconds long milliseconds = unixTime.total!"msecs"; // Print the Unix time in milliseconds writeln("Unix time in milliseconds: ", milliseconds); }
Get milliseconds from time and construct time based on milliseconds
I have two questions that I can't seem to find a solution to after looking at std.datetime. First question is how do I get the current time but in milliseconds? Second is how do I construct a time ex. systime or datetime based on milliseconds? Thanks
Re: Hide console on Windows with app running SDL2
On Tuesday, 28 May 2024 at 12:45:39 UTC, Steven Schveighoffer wrote: On Tuesday, 28 May 2024 at 12:35:42 UTC, bauss wrote: Running into a couple of problems trying to hide the console that opens when running an app that uses sdl2. First of all I am trying to compile with this using dub: ``` "lflags": ["/SUBSYSTEM:windows"] ``` However that gives me the following error: ``` error LNK2019: unresolved external symbol WinMain ``` And then if I add a WinMain like below: ``` extern (Windows) int WinMain() { return 0; } ``` Then of course it doesn't work, but what is the obvious way to solve this? I basically just want to hide the console, but nothing seems to work straight out of the box. I think this is still relevant: https://wiki.dlang.org/D_for_Win32 -Steve Thanks a lot, that helped and solved the issue
Re: Hide console on Windows with app running SDL2
On Tuesday, 28 May 2024 at 12:35:42 UTC, bauss wrote: Running into a couple of problems trying to hide the console that opens when running an app that uses sdl2. First of all I am trying to compile with this using dub: ``` "lflags": ["/SUBSYSTEM:windows"] ``` However that gives me the following error: ``` error LNK2019: unresolved external symbol WinMain ``` And then if I add a WinMain like below: ``` extern (Windows) int WinMain() { return 0; } ``` Then of course it doesn't work, but what is the obvious way to solve this? I basically just want to hide the console, but nothing seems to work straight out of the box. I think this is still relevant: https://wiki.dlang.org/D_for_Win32 -Steve
Re: Implementation Details
On 28/05/2024 12:54 PM, Ruby The Roobster wrote: As of late, I have taken up an interest in learning about how the D language is implemented at a compiler level, specifically the GC implementation. Unfortunately, the source code is poorly documented, and is too large to simply read all of it in a reasonable amount of time. If anyone here can help me, or at least point me to relevant resources, I would be very grateful. From a theory standpoint this book should give you a pretty good overview of how GC's work. It is the book I recommend for introduction to GC's. https://www.amazon.com/Garbage-Collection-Handbook-International-Perspectives-dp-1032218037/dp/1032218037/ref=dp_ob_title_bk But yes that GC is very hard to get into, and its been tacked on over the years which make it even harder to untangle. Plus there is a memory allocator in there too.
Implementation Details
As of late, I have taken up an interest in learning about how the D language is implemented at a compiler level, specifically the GC implementation. Unfortunately, the source code is poorly documented, and is too large to simply read all of it in a reasonable amount of time. If anyone here can help me, or at least point me to relevant resources, I would be very grateful.
Re: Problem with clear on shared associative array?
On 28/05/2024 12:36 PM, Andy Valencia wrote: On Monday, 27 May 2024 at 04:04:03 UTC, mw wrote: Pls NOTE: it is a `sharded` (meaning trunk-ed) NON-concurrent map, not `shared` concurrent map. Assuming I put it in shared memory, in what way is it not able to be used concurrently? It seems to have the needed lock operations? Thanks, Andy A concurrent data structure handles all of this for you. AA's are not concurrent because it doesn't offer any protection. Protecting a data structure with a mutex doesn't make it concurrent, but it may allow you to use it concurrently safely. Subtle difference!
Re: Problem with clear on shared associative array?
On Monday, 27 May 2024 at 04:04:03 UTC, mw wrote: Pls NOTE: it is a `sharded` (meaning trunk-ed) NON-concurrent map, not `shared` concurrent map. Assuming I put it in shared memory, in what way is it not able to be used concurrently? It seems to have the needed lock operations? Thanks, Andy
Re: Problem with clear on shared associative array?
On Monday, 27 May 2024 at 00:43:47 UTC, Serg Gini wrote: On Sunday, 26 May 2024 at 20:15:54 UTC, Andy Valencia wrote: For others wrestling with this issue, I found out how to cast to unshared at this article: You can check also this solution https://github.com/DmitryOlshansky/sharded-map Pls NOTE: it is a `sharded` (meaning trunk-ed) NON-concurrent map, not `shared` concurrent map. These two words looks similar, but the meaning is very different.
Re: Problem with clear on shared associative array?
On Sunday, 26 May 2024 at 20:15:54 UTC, Andy Valencia wrote: For others wrestling with this issue, I found out how to cast to unshared at this article: You can check also this solution https://github.com/DmitryOlshansky/sharded-map
Re: Problem with clear on shared associative array?
On Sunday, 26 May 2024 at 20:00:50 UTC, Jonathan M Davis wrote: No operation on an associative array is thread-safe. As such, you should not be doing _any_ operation on a shared AA without first locking a mutex to protect it. Then you need to cast away shared to access or mutate it or do whatever it is you want to do with it other than pass it around. And then when you're done, you make sure that no thread-local references to the AA exist, and you release the mutex. ... Thank you, that's exactly the big picture explanation I was hoping for. For others wrestling with this issue, I found out how to cast to unshared at this article: https://forum.dlang.org/thread/jwasqvrvkpqzimlut...@forum.dlang.org Andy
Re: Problem with clear on shared associative array?
On Sunday, May 26, 2024 8:39:53 AM MDT Andy Valencia via Digitalmars-d-learn wrote: > The following code fails to compile; it appears from the error > message that the library's clear() function is not ready to act > on a shared AA? > > synchronized class F { > > private: > string[int] mydict; > > public: > void clear() { > this.mydict.clear(); > } > } > > void > main() > { > auto f = new shared F(); > f.clear(); > } No operation on an associative array is thread-safe. As such, you should not be doing _any_ operation on a shared AA without first locking a mutex to protect it. Then you need to cast away shared to access or mutate it or do whatever it is you want to do with it other than pass it around. And then when you're done, you make sure that no thread-local references to the AA exist, and you release the mutex. This is true for any type which is not specifically designed to be shared, and none of the built-in types are designed to be shared. They will work as shared so long as you protect them appropriately and then temporarily cast away shared to operate on them as thread-local, but they should never be mutated as shared, and it's on you to make sure that the object is actually protected appropriately when you cast away shared, since the language has no way of knowing when that's actually safe to do. It can just prevent you from accidentally accessing an object when it's shared, since when it's shared, the type system marks it as shared across threads and thus not thread-safe to access. The language is supposed to prevent you from doing any operations on a shared object which are not guaranteed to be thread-safe (which is pretty much anything other than passing it around by reference or pointer), but unfortunately, since that wasn't entirely implemented up front, some of those checks are currently behind the -preview=nosharedaccess flag and will be made the default at some point in the future (but not now). So, some shared operations may work when they really shouldn't, but the compiler will prevent you from calling a function like clear, because it operates on thread-local variables, not shared ones. And with regards to AAs, you will need to be particularly careful with the in operator, because it returns a pointer a value in the AA. So, if you cast away shared to operate on it and then use in, you'll get a thread-local pointer to the AA, meaning that the lock needs to stay in place as long as that pointer is around, whereas a function like clear is done as soon as its been called, so unless you're doing more with the AA at that point, you could release the lock then. Using synchronized is one way to get a mutex, and a synchronized function is implicitly shared, so your clear function is both synchronized and shared, meaning that you can call it on a shared object, and it will lock a mutex when it's called, but you still need to cast away shared from mydict to be able to call anything on it. The compiler is not smart enough to know that removing shared is thread-safe within your function, so it will not do it for you, and the clear function for AAs can't work on shared AAs, because it has no way of guaranteeing that that's thread-safe. So, the solution is that you must explicitly removed shared temporarily to call clear when you know that it's thread-safe to do so. - Jonathan M Davis
Problem with clear on shared associative array?
The following code fails to compile; it appears from the error message that the library's clear() function is not ready to act on a shared AA? synchronized class F { private: string[int] mydict; public: void clear() { this.mydict.clear(); } } void main() { auto f = new shared F(); f.clear(); }
Re: How does one attach a manifest file to a D executable on Windows?
On Saturday, 25 May 2024 at 13:13:08 UTC, solidstate1991 wrote: No, I meant something like this: https://learn.microsoft.com/en-us/windows/win32/controls/cookbook-overview Not tested but from memory I do this: 1) Copy that first XML snippet from the page you linked, save to a file called example.exe.manifest 2) Create a resource script file called resources.rc, with this at the top: 1 24 "example.exe.manifest" 3) Compile it with rc.exe 4) Include the resulting resources.res on your DMD command line You might also need to call InitCommonControls or InitCommonControlsEx before creating any windows.
Re: How does one attach a manifest file to a D executable on Windows?
On Friday, 24 May 2024 at 21:26:12 UTC, Ferhat Kurtulmuş wrote: I think this is what you need https://github.com/aferust/doitlater/tree/master/views/res No, I meant something like this: https://learn.microsoft.com/en-us/windows/win32/controls/cookbook-overview
Re: Parallel safe associative array?
https://code.dlang.org/packages/rust_interop_d wrapped: DashMap: is an implementation of a concurrent associative array/hashmap in Rust.
Re: How does one attach a manifest file to a D executable on Windows?
On Friday, 24 May 2024 at 21:04:53 UTC, Ferhat Kurtulmuş wrote: On Friday, 24 May 2024 at 19:07:24 UTC, solidstate1991 wrote: I have tried resource compiling, then using `dflags` in dug to add the resulting obj file, but I still get the issue of the old GUI style. I did that before, but I don't remember now. Probably you will figure that out based on this. https://gitlab.com/aferust/gtkdappcreator/-/tree/master/win_res?ref_type=heads I think this is what you need https://github.com/aferust/doitlater/tree/master/views/res
Re: How does one attach a manifest file to a D executable on Windows?
On Friday, 24 May 2024 at 19:07:24 UTC, solidstate1991 wrote: I have tried resource compiling, then using `dflags` in dug to add the resulting obj file, but I still get the issue of the old GUI style. I did that before, but I don't remember now. Probably you will figure that out based on this. https://gitlab.com/aferust/gtkdappcreator/-/tree/master/win_res?ref_type=heads
Parallel safe associative array?
I was playing with parallel programming, and experienced "undefined behavior" when storing into an Associative Array in parallel. Guarding the assignments with a synchronized barrier fixed it, of course. And obviously loading down your raw AA with thread barriers would be foolish. But this set me searching through the library for a standard Associative Array construct which _is_ thread safe? It didn't jump out at me. I know I can place such a thing within a synchronized class, but I was wondering if there's a standard AA which has the standard usage but is safe when called in parallel? Thanks, Andy
Re: Recommendations on porting Python to D
On Friday, 3 May 2024 at 17:53:41 UTC, mw wrote: On Friday, 3 May 2024 at 17:38:10 UTC, Chris Piker wrote: On Thursday, 25 April 2024 at 16:57:53 UTC, mw wrote: [...] Thanks for the suggestions. I put the question aside for a bit, but yesterday ran across a python transpiler here: https://github.com/py2many/py2many It already has support for C++, Go and others. Since I have mountains of python code created over many years, maybe it would be worth contributing to this project out of self interest. Can you take a look at py2many and see what you think about it? Getting D on the support list might be good. (Haven't checked its own implementation and output code quality.) But it says has output for Kotlin, Dart, these two languages are similar to D syntactically, so will be a good start. I took another quick look of the project, it uses the Python builtin `ast` module as parser, and visitor design pattern to implement the transcompiler, so I think it's of decent quality. HTH.
Re: Anybody know about SDL and particularly SDL_TTF initialization?
On Sunday, 12 May 2024 at 20:13:04 UTC, WhatMeWorry` wrote: INFO: SDL loaded v2.30.2 INFO: SDL initialized: 0 INFO: TTF loaded: v2.0.14 Error Program exited with code -1073741819 Something hit a null pointer, time to fire up the debugger :)
Re: Anybody know about SDL and particularly SDL_TTF initialization?
On Sunday, 12 May 2024 at 20:13:04 UTC, WhatMeWorry` wrote: This should be trivial, right? I've been looking at existing D repo code for hours. Can't figure why TTF_Init doesn't work? It would help if I could figure out how to use SDL_GetError() INFO: SDL loaded v2.30.2 INFO: SDL initialized: 0 INFO: TTF loaded: v2.0.14 Error Program exited with code -1073741819 loadSDL(); SDL_version v; SDL_GetVersion(); toStdout("SDL loaded v%d.%d.%d", v.major, v.minor, v.patch); auto initSDL = SDL_Init(SDL_INIT_EVERYTHING); // returns 0 on success toStdout("SDL initialized: %d", initSDL); auto loadTTF = loadSDLTTF(); SDL_TTF_VERSION(); toStdout("TTF loaded: v%d.%d.%d", v.major, v.minor, v.patch); auto initTTF = TTF_Init(); // SDL must be initialized before calls to this library No idea why this fails, seems alright to me. You can use: TTF_GetError() for a human-readable error message,when the call to TTF_Init() fails (return -1). Good luck Danny
Re: __gshared is "somewhat" transitive, isn't it ?
On Thursday, 16 May 2024 at 17:04:09 UTC, user1234 wrote: Given ```d struct S { int member; } __gshared S s; ``` It's clear that `s.member` is `__gshared` too, right ? What does happen for ```d struct S { int member; static int globalMember; } __gshared S s; ``` Is then `S.globalMember` a TLS variable ? (I'd expect that) `__gshared` is a storage class. It means, store this thing in the global memory segment. `static` storage class means store this thing in TLS. Storage classes are *not* transitive, and they are not type constructors. They optionally might apply a type constructor to the type (such as the `const` storage class), but not always. So in this case `typeof(s)` is `S`, not `__gshared S`. `s.member` is in the global segment since structs members are placed within the struct memory location (in this case, the global memory segment). `globalMember` is placed in TLS because it's storage class is `static`, and `static` means, do not store with the instance (which for `s` would mean the global memory segment), but rather in TLS. -Steve
Re: Setting field of struct object
On Monday, 22 January 2024 at 08:54:21 UTC, Danilo wrote: On Monday, 22 January 2024 at 08:35:01 UTC, Joel wrote: [...] Nonetheless, this usually used with Objects (new class/struct instances), like so: ```d import std; [...] Fluent Interface
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: Also try the code I gave in this thread: https://forum.dlang.org/post/fgzvdhkdyevtzznya...@forum.dlang.org In fact, please use this facility in the standard library: https://dlang.org/phobos/std_datetime_stopwatch.html#benchmark SDB@79
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: real0m1.589s user0m1.585s sys 0m0.004s And the dlist based one: real0m4.731s user0m5.211s sys 0m0.308s Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? The code is spaghetti, fifo/dlist, but it seemed the easiest way to see the two API's being used side by side: version(fifo) { import tiny.fifo : FIFO; } else { import std.container.dlist : DList; } const uint ITERS = 10_000; const uint DEPTH = 10_000; void main() { version(fifo) { auto d = FIFO!uint(); } else { auto d = DList!uint(); } foreach(_; 0 .. ITERS) { foreach(x; 0 .. DEPTH) { version(fifo) { d.add(x); } else { d.insertBack(x); } } foreach(x; 0 .. DEPTH) { version(fifo) { assert(x == d.next()); } else { assert(x == d.front()); d.removeFront(); } } } } thank you for sharing the results. Everything I read about queues recommends doublylinked lists. With your array based implementatio if you are consuming the elements faster than pushing new elements, your array buffer never resize which is costly. This should explain why your array based queue is more performant.
Re: FIFO
On Monday, 13 May 2024 at 15:07:39 UTC, Andy Valencia wrote: Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? I know you want FIFO, I usually keep this on hand for fixed size LIFO; It can easily convert to FIFO and doesn't use LinkedList: ```d class LIFO(T) { T * element; size_t length, size; this(size_t s) { element = cast(T*)new T[s]; length = s; } auto rewind() => size = length; bool empty() => !size; auto front() => element[size - 1]; auto popFront() => --size; auto pop() => empty ? T(0) : element[--size]; alias push = insertFront; auto insertFront(T value) in(size < length, "Stack is overflow!") => element[size++] = value; auto ref opDollar() => length; auto ref opIndex(size_t i) => element[i]; auto ref opSlice(size_t first, size_t last) => element[first..last]; } unittest { enum test = 7; auto stack = new LIFO!size_t(test); assert(!stack.size); foreach (prime; 1..test + 1) { stack.insertFront(prime); } assert(stack.size == test); // == 7 stack.writeln(": ", stack.length); // [7, 6, 5, 4, 3, 2, 1]: 7 stack[$/2].writeln("-", stack[0]); // 4-1 stack.rewind(); stack.size.write(": ["); // 10: while (auto next = stack.pop) { if (next == 1) next.writeln("]"); else next.write(", "); } stack.size.writeln; // 0 stack.rewind(); assert(stack.size == test); } SDB@79
Re: FIFO
On Sunday, 12 May 2024 at 22:03:21 UTC, Ferhat Kurtulmuş wrote: https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Ahh yes. Then use dlist Thank you. I read its source, and was curious so I wrote a small performance measurement: put 10,000 things in a FIFO, pull them back out, and loop around that 10,000 times. My FIFO resulted in: real0m1.589s user0m1.585s sys 0m0.004s And the dlist based one: real0m4.731s user0m5.211s sys 0m0.308s Representing the FIFO as a linked list clearly has its cost, but I found the increased system time interesting. OS memory allocations maybe? The code is spaghetti, fifo/dlist, but it seemed the easiest way to see the two API's being used side by side: version(fifo) { import tiny.fifo : FIFO; } else { import std.container.dlist : DList; } const uint ITERS = 10_000; const uint DEPTH = 10_000; void main() { version(fifo) { auto d = FIFO!uint(); } else { auto d = DList!uint(); } foreach(_; 0 .. ITERS) { foreach(x; 0 .. DEPTH) { version(fifo) { d.add(x); } else { d.insertBack(x); } } foreach(x; 0 .. DEPTH) { version(fifo) { assert(x == d.next()); } else { assert(x == d.front()); d.removeFront(); } } } }
Re: What prevents ImportC from using .h directly?
On Sunday, 12 May 2024 at 21:34:30 UTC, Chris Piker wrote: So, why does ImportC need *.c files exclusively? I'm sure it solves a problem, but I don't know what that problem is. Support for headers has been worked on, but had to be reverted: https://issues.dlang.org/show_bug.cgi?id=23479
Re: Find homography in D?
On Sunday, 21 April 2024 at 14:57:33 UTC, Paolo Invernizzi wrote: Hi, Someone can point me to a D implementation of the classical OpenCV find homography matrix? Thank you, Paolo Now, we can do image stitching using DCV. It needs improvements though. https://github.com/libmir/dcv/tree/master/examples/imagestitchinghomography
Re: FIFO
On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! [...] I don't know your use case, maybe you have a similar problem I had to solve years ago. https://forum.dlang.org/post/xktftztisodpngcow...@forum.dlang.org
Re: FIFO
On Sunday, 12 May 2024 at 21:08:24 UTC, Andy Valencia wrote: On Sunday, 12 May 2024 at 19:45:44 UTC, Ferhat Kurtulmuş wrote: On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. ... https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Andy Ahh yes. Then use dlist
What prevents ImportC from using .h directly?
Hi D Import D is working quite well so far. One limitation is that module definitions require a tiny *.c file which is often just: ```C #include ``` Creating this file is trivial and has almost no knock-on effects, except when dealing with single file programs. I have quite a few small utilities with dub headers. It would be handy if I could set an import path and use ImportC on the header file directly, skipping the small C file all together. A specific example in my case follows. Given a C-lib interface defined in the header file: ``` /usr/include/cspice/SpiceUsr.h ``` it would be neat if a dub header similar to the following worked: ```d #!/usr/bin/env dub /+ dub.sdl: name "some_app" cImportPaths "/usr/local/include/cspice" +/ import SpiceUsr; // ... source continues ``` So, why does ImportC need *.c files exclusively? I'm sure it solves a problem, but I don't know what that problem is.
Re: FIFO
On Sunday, 12 May 2024 at 19:45:44 UTC, Ferhat Kurtulmuş wrote: On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. ... https://dlang.org/phobos/std_container_slist.html This is a stack, isn't it? LIFO? Andy
Anybody know about SDL and particularly SDL_TTF initialization?
This should be trivial, right? I've been looking at existing D repo code for hours. Can't figure why TTF_Init doesn't work? It would help if I could figure out how to use SDL_GetError() INFO: SDL loaded v2.30.2 INFO: SDL initialized: 0 INFO: TTF loaded: v2.0.14 Error Program exited with code -1073741819 loadSDL(); SDL_version v; SDL_GetVersion(); toStdout("SDL loaded v%d.%d.%d", v.major, v.minor, v.patch); auto initSDL = SDL_Init(SDL_INIT_EVERYTHING); // returns 0 on success toStdout("SDL initialized: %d", initSDL); auto loadTTF = loadSDLTTF(); SDL_TTF_VERSION(); toStdout("TTF loaded: v%d.%d.%d", v.major, v.minor, v.patch); auto initTTF = TTF_Init(); // SDL must be initialized before calls to this library
Re: FIFO
On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! [...] "next" is not a usual range primitive word in dlang. Why not just using slist.
Re: FIFO
On Saturday, 11 May 2024 at 23:44:28 UTC, Andy Valencia wrote: I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! [...] https://dlang.org/phobos/std_container_slist.html
Re: Deprecation: foreach: loop index implicitly converted from size_t to int
A horrible alternative would be to use `alias` on `size_t` to make up a new pseudo-type that is more aligned with the code logic. ``` alias integer = size_t; import std.stdio : writefln; void main() { auto arr = [ [5, 15], // 20 [2, 3, 2, 3], // 10 [3, 6, 2, 9], // 20 ]; foreach (integer i, row; arr) { double total = 0.0; foreach (e; row) total += e; auto avg = total / row.length; writefln("AVG [row=%d]: %.2f", i, avg); } } ```
FIFO
I need a FIFO for a work scheduler, and nothing suitable jumped out at me. I wrote the following, but as a newbie, would be happy to receive any suggestions or observations. TIA! /* * fifo.d * FIFO data structure */ module tiny.fifo; import std.exception : enforce; const uint GROWBY = 16; /* * This is a FIFO, with "hd" walking forward and "tl" trailing * behind: *tl hd /Add here next *v v * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 * * Mildly complicated by a module-size indexing. */ struct FIFO(T) { T[] items; ulong hd, tl, length; void add(T t) { // Make more room when needed if (this.items.length == this.length) { assert(this.hd == this.tl); // Add room and shuffle current contents auto olen = this.items.length; auto newlen = olen + GROWBY; this.items.length = newlen; this.tl = (this.tl + GROWBY) % newlen; // Shuffle what we're butted up against to their // new position at the top of this.items[] ulong moved = olen - this.hd; this.items[$ - moved .. $] = this.items[this.hd .. this.hd + moved]; } // Add item at next position this.items[hd] = t; this.hd = (this.hd + 1) % this.items.length; this.length += 1; } // Give back next T next() { enforce(this.length > 0, "next() from empty FIFO"); this.length -= 1; auto res = this.items[this.tl]; this.tl = (this.tl + 1) % this.items.length; return res; } } unittest { auto f = FIFO!uint(); f.add(1); f.add(2); f.add(3); assert(f.next() == 1); assert(f.next() == 2); assert(f.next() == 3); assert(f.length == 0); // Now overflow several times f = FIFO!uint(); foreach(x; 0 .. GROWBY * 3 + GROWBY/2) { f.add(x); } foreach(x; 0 .. GROWBY * 3 + GROWBY/2) { assert(f.next() == x); } assert(f.length == 0); } version(unittest) { void main() { } }
Re: How to load a DLL file in D?
On Saturday, 11 May 2024 at 20:04:38 UTC, Lance Bachmeier wrote: On Saturday, 11 May 2024 at 19:33:03 UTC, solidstate1991 wrote: I know that BindBC exists and otherwise would use it, but the bigger the library, the more extra hurdle it'll have. When I did a few bindings with it, I had to order the functions the right way, so I could do things much quicker with the Ctrl+Alt+Shift trick under VSCode, and even then having to write both a statically linked and dynamically linked version (the latter which required the functions to be loaded individually into function pointers). Maybe I should write some automation tool... You might find this package useful https://code.dlang.org/packages/dynamic Also relevant if they're C functions: https://forum.dlang.org/post/qxctappnigkwvaqak...@forum.dlang.org And this if you want to convert C headers to D code: https://forum.dlang.org/post/ugvc3o$5t3$1...@digitalmars.com
Re: How to load a DLL file in D?
On Saturday, 11 May 2024 at 19:33:03 UTC, solidstate1991 wrote: I know that BindBC exists and otherwise would use it, but the bigger the library, the more extra hurdle it'll have. When I did a few bindings with it, I had to order the functions the right way, so I could do things much quicker with the Ctrl+Alt+Shift trick under VSCode, and even then having to write both a statically linked and dynamically linked version (the latter which required the functions to be loaded individually into function pointers). Maybe I should write some automation tool... You might find this package useful https://code.dlang.org/packages/dynamic
Re: Why is Phobos `Flag` so overthought ?
On Thursday, 9 May 2024 at 18:48:12 UTC, Nick Treleaven wrote: We have a tool in our box already called `true` and that solves the problem. If we had to type out the full name of every argument passed to every function ever written we may as well just adopt ObjC Cocoa style and call it StopWatchWithAutoStartBool(). Strawman. Not at all. I mean exactly that. Why do you believe this function is so important it needs to have its argument type explicitly stated, when most functions don't? Either that, or you believe all functions should. It's arbitrary and pointless.
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 16:33:53 UTC, Nick Treleaven wrote: Arrays evaluate to true in boolean conditions if their `.ptr` field is non-null. This is bug-prone and I hope we can remove this in the next edition. ... A string literal's `.ptr` field is always non-null, because it is null-terminated. Thank you! Andy
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 15:23:39 UTC, Andy Valencia wrote: On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer wrote: Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true. Arrays evaluate to true in boolean conditions if their `.ptr` field is non-null. This is bug-prone and I hope we can remove this in the next edition. However, although I thought a string was basically an immutable array of characters, "" is treated as true, not false? A string literal's `.ptr` field is always non-null, because it is null-terminated.
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 03:07:43 UTC, Steven Schveighoffer wrote: Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). So if I may ask for one more small clarification... WRT "truthiness", I've observed that empty arrays are treated as false, non-empty as true. However, although I thought a string was basically an immutable array of characters, "" is treated as true, not false? Thanks again, Andy
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
On Friday, 10 May 2024 at 13:27:40 UTC, Dukc wrote: Steven Schveighoffer kirjoitti 10.5.2024 klo 16.01: On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote: This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! This would be weak pure since the reference is mutable. This cannot be memoized. The difference is the type. With a pointer parameter (both a bare one and one in a struct), the compiler can cache the result only when the pointed data is similar. However, here we have an integer parameter. It can be cached if it itself is similar to the one in the other function call. The compiler doesn't have to know, nor can know, when a `size_t` is a pointer in disguise. This why I would just use ref counting if I were the topic author, trying to be smart will often comes back when one doesn't expect. And as stated by previous author if the goal is to have self-clearable weak reference it will need some infrastructure anyway, so tbh this will greatly outweight any possible benefits of having weak refs.
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
Steven Schveighoffer kirjoitti 10.5.2024 klo 16.01: On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote: This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! This would be weak pure since the reference is mutable. This cannot be memoized. The difference is the type. With a pointer parameter (both a bare one and one in a struct), the compiler can cache the result only when the pointed data is similar. However, here we have an integer parameter. It can be cached if it itself is similar to the one in the other function call. The compiler doesn't have to know, nor can know, when a `size_t` is a pointer in disguise.
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
On Friday, 10 May 2024 at 11:05:28 UTC, Dukc wrote: This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! This would be weak pure since the reference is mutable. This cannot be memoized. -Steve
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
evilrat kirjoitti 9.5.2024 klo 18.19: ```d struct WeakRef(T) { private size_t _handle; // same size as a pointer this(T* ptr) { _handle = cast(size_t) ptr; } T* getRef() { return cast(T*) _handle; } // do the rest ... } ``` [1] https://code.dlang.org/packages/automem There is a hidden danger with using this struct. Since `getRef` is a template, it will be inferred as `pure`. Now, consider a function using it: ```D auto derefer(WeakrefT)(WeakrefT wr) => *wr.getRef; ``` This also gets inferred as `pure` - meaning that if you use it twice for the same `WeakRef`, the compiler may reuse the result of the first dereference for the second call, without checking whether the referred value has changed! You probably should add some never-executed dummy operation to `getRef` that prevents it from becoming `pure` if you go with this design.
Re: moving from classical lex/yacc to pegged parser
Dmitry Ponyatov kirjoitti 9.5.2024 klo 11.30: > And I also can't figure out how to inherit `ParseTree` with all my script language objects to get AST right from pegged parser. Should I use some superloop with lot of matches to process parsed `pt` tree into something I need myself, to drop all unneeded parsing meta info and get clean semantic AST? Pegged can help you with that filtering part, at least to some extent. Remember you can use : and ; prefix operators in the grammar spec, and Pegged will drop the needless nodes for you. Or do the reverse, use ^ prefix operator (or write a new rule) to make a node out of Pegged builtins.
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 01:00:09 UTC, Andy Valencia wrote: On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote: Yes. The reason for this is that it avoids having to essentially do the same check twice. If `in` returned a bool instead of a pointer, after checking for whether the element exists (which requires searching for the element in the associative array), you'd then have to actually *get* it from the array, which would require searching again. Returning a pointer to the element if it exists (or `null` if it doesn't) cuts this down to 1 operation. Looking at Programming in D section 28.5, I'm guessing that pointer versus null is treated as the appropriate boolean value when consumed by an "if" test. So that example is getting a pointer to a string, or null, but the example looks exactly as the same as if it had directly gotten a bool. Yes, we say that a type has "truthiness" if it can be used in a condition (`while`, `if`, `assert`, etc). For a pointer, `null` is considered "false", whereas any other value is considered "true". So you can use statements like `if(key in aa)` to test for membership. A very nice idiom is to check if a key is in an associative array, and if so, use the value that it maps to: ```d if(auto v = key in aa) { // use *v as the value here } ``` You can change your code to `return (e in this.members) !is null;` -Steve
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 00:40:01 UTC, Meta wrote: Yes. The reason for this is that it avoids having to essentially do the same check twice. If `in` returned a bool instead of a pointer, after checking for whether the element exists (which requires searching for the element in the associative array), you'd then have to actually *get* it from the array, which would require searching again. Returning a pointer to the element if it exists (or `null` if it doesn't) cuts this down to 1 operation. Looking at Programming in D section 28.5, I'm guessing that pointer versus null is treated as the appropriate boolean value when consumed by an "if" test. So that example is getting a pointer to a string, or null, but the example looks exactly as the same as if it had directly gotten a bool. Thank you! Andy
Re: "in" operator gives a pointer result from a test against an Associative Array?
On Friday, 10 May 2024 at 00:18:16 UTC, Andy Valencia wrote: tst7.d(6): Error: cannot implicitly convert expression `e in this.members` of type `bool*` to `bool` tst7.d(15): Error: template instance `tst7.Foo!uint` error instantiating I'm getting this for this bit of source (trimmed from the bigger code). I switched to this.members.get(e, false) and that works fine, but I'm still curious: struct Foo(T) { bool[T] members; bool has(T e) { return (e in this.members); } } void main() { import std.stdio : writeln; auto t = Foo!uint(); writeln(t.has(123)); } Yes. The reason for this is that it avoids having to essentially do the same check twice. If `in` returned a bool instead of a pointer, after checking for whether the element exists (which requires searching for the element in the associative array), you'd then have to actually *get* it from the array, which would require searching again. Returning a pointer to the element if it exists (or `null` if it doesn't) cuts this down to 1 operation.
"in" operator gives a pointer result from a test against an Associative Array?
tst7.d(6): Error: cannot implicitly convert expression `e in this.members` of type `bool*` to `bool` tst7.d(15): Error: template instance `tst7.Foo!uint` error instantiating I'm getting this for this bit of source (trimmed from the bigger code). I switched to this.members.get(e, false) and that works fine, but I'm still curious: struct Foo(T) { bool[T] members; bool has(T e) { return (e in this.members); } } void main() { import std.stdio : writeln; auto t = Foo!uint(); writeln(t.has(123)); }
Re: Why is Phobos `Flag` so overthought ?
On Wednesday, 8 May 2024 at 10:24:07 UTC, Nick Treleaven wrote: Named arguments are optional, so I don't see how they could make Flag redundant. Actually, an external tool could detect when a bool is passed as an argument to a function and warn when not done with a named argument. This would free library APIs from having to use Flag when some users don't care about it. The cost would come in a bit more build system complexity/build time, which might mean a lot less enforcement due to inertia. Though maybe a reasonable trade-off.
Re: Why is Phobos `Flag` so overthought ?
On Thursday, 9 May 2024 at 13:40:56 UTC, cc wrote: It's pointless mandatory verbosity. StopWatch ctor only takes one boolean argument. It doesn't *need* to specify what it relates to. You either already know, or you have to look it up anyway. Flags made sense when you might get the order of multiple bools confused, but if there's only one, *or* if you can use named arguments to avoid ambiguity, So you have justified Flag. there's no point in demanding every parameter be a unique type. It's easy to remember I can pass a bool to a StopWatch to autostart it. But perhaps true means manual start? Remembering can also be used to justify dynamic typing outside of hot loops, I'd rather not rely on remembering with a big team of programmers working on a project. It's less easy to remember that a specific unique type needs to be used, and remembering whether the name/casing of that type was Start, StartNow, StartAuto, Autostart, AutoStart, autostart, autoStart, etc. So just pass it true, and run the compiler. The compiler will tell you what the correct type is. We have a tool in our box already called `true` and that solves the problem. If we had to type out the full name of every argument passed to every function ever written we may as well just adopt ObjC Cocoa style and call it StopWatchWithAutoStartBool(). Strawman.
Re: D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
On Thursday, 9 May 2024 at 00:39:49 UTC, Liam McGillivray wrote: What's a good way I can achieve what I'm trying to do, using either reference counting or a garbage-collected object? There is libraries like `automem`[1] that implements refcounting and more. Without showing your code for ref counted struct we can't help you. As for weak references, maybe you could "trick" the GC by using the fact that simple types are not scanned, i.e. do something like this but I have no idea if this is going to work at all, alternatively you can also try using `ubyte[size_t.sizeof]`. Keep in mind that classes is already references so you don't need that extra pointer for classes, can be versioned with template specialization. ```d struct WeakRef(T) { private size_t _handle; // same size as a pointer this(T* ptr) { _handle = cast(size_t) ptr; } T* getRef() { return cast(T*) _handle; } // do the rest ... } ``` [1] https://code.dlang.org/packages/automem
Re: Why is Phobos `Flag` so overthought ?
On Wednesday, 8 May 2024 at 10:24:07 UTC, Nick Treleaven wrote: On Wednesday, 8 May 2024 at 04:27:13 UTC, cc wrote: It doesn't allow a simple boolean to be used as an argument, or any other Flag as they are different instantiations of a template rather than equivalent aliases. It is however awful, cumbersome, annoying design and needs to be completely phased out now that we have named arguments. Flag enforces that the argument says what it relates to. `true` does not say what it relates to. Named arguments are optional, so I don't see how they could make Flag redundant. It's pointless mandatory verbosity. StopWatch ctor only takes one boolean argument. It doesn't *need* to specify what it relates to. You either already know, or you have to look it up anyway. Flags made sense when you might get the order of multiple bools confused, but if there's only one, *or* if you can use named arguments to avoid ambiguity, there's no point in demanding every parameter be a unique type. It's easy to remember I can pass a bool to a StopWatch to autostart it. It's less easy to remember that a specific unique type needs to be used, and remembering whether the name/casing of that type was Start, StartNow, StartAuto, Autostart, AutoStart, autostart, autoStart, etc. We have a tool in our box already called `true` and that solves the problem. If we had to type out the full name of every argument passed to every function ever written we may as well just adopt ObjC Cocoa style and call it StopWatchWithAutoStartBool().
moving from classical lex/yacc to pegged parser
Using lex/yacc I can do a more or less complex things in .yacc semantic actions, such complex as bytecode compilation or real CPU assembly. Playing with `pegged`, I can't figure out how to move from `ParseTree` to such like semantic actions. I even can't parse numbers from strings in lexer-like rules because it looks like every rule runs on any token parse, or sumething like this. Also, I use attribute object trees resemble attribute grammar both for parsing and internal code representation: ```C++ class Object { string value; // or `int value` and `float value` for numbers map attr; vector nested; } ``` And I also can't figure out how to inherit `ParseTree` with all my script language objects to get AST right from pegged parser. Should I use some superloop with lot of matches to process parsed `pt` tree into something I need myself, to drop all unneeded parsing meta info and get clean semantic AST?
D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?
A "weak reference" (in the sense that I'm referring to) is a feature in some programming languages for a reference to an object that doesn't prevent the GC from destroying that object. My current understanding is that D doesn't have weak references, though I've found some posts in this forum from many years back that mention something called "weakref". So is weakref a real thing, or just a concept that never got implemented? The functionality that I'm going to describe would be easy with weak references, but I don't know how I would implement it without it. If there is a way to implement it without it, I would like to know how. I am going to describe my specific example, but it may apply to any class that's initialized using contents of a file without any of that data being modified after. In my particular case, the class I've created is a wrapper for the `Texture2D` struct in Raylib. This class holds an image that was loaded from a file. ``` Sprite[string] spritesByPath; Sprite getSprite(string path) { path = path.asAbsolutePath; if (path !in spritesByPath) { spritesByPath[path] = new Sprite(path); } return spritesByPath[path]; } class Sprite { Texture2D texture; alias this = texture; string path; this(string path) { texture = LoadTexture(path.toStringz); this.path = path; } ~this() { if (IsWindowReady) UnloadTexture(texture); if (path in spritesByPath) spritesByName.remove(path); } } ``` Alternatively, `spritesByPath` and `getSprite` may be static members of `Sprite`. If D had weak references, than `spritesByPath` would be made of weak references so that they don't prevent the destruction of `Sprite` objects, which should be destroyed whenever they don't have any references elsewhere. I've considered making `Sprite` reference-counted, but I couldn't manage to figure out how to do it properly. I tried doing `SafeRefCounted!Sprite` but the compiler said it doesn't work on `Object` types. I then tried making my own struct for reference counting that would be placed in place of a direct reference to the `Sprite` object, but there was some bug in which sometimes it didn't increment the reference count, so it didn't work. What's a good way I can achieve what I'm trying to do, using either reference counting or a garbage-collected object?
Re: How can I put the current value of a variable into a delegate?
On Wednesday, 8 May 2024 at 12:29:05 UTC, Rene Zwanenburg wrote: Interestingly enough C# used to have the same behaviour but MS decided to go for a breaking change in C# 5; now it behaves as most people expect. Wow! I wonder if D would be willing to allow such a breaking change with the release of Phobos 3. My choice would be to have it use the current value by default for value types, but allow them to be linked to the same memory address using `*&` when the variable is placed in a delegate. I think that the distinction between value types and reference types should be consistent. If such a breaking change isn't considered acceptable, I suppose a new operator can be introduced for dereferencing a variable when placed in a delegate. Maybe `#` or `$` if they don't conflict with any existing use of those symbols.
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 16:41:38 UTC, Steven Schveighoffer wrote: On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote: Delegates can be a pain, as they often have results different from what one would intuitively expect. This can easily result in bugs. Here's a line that caused a bug that took me awhile to find: ``` foreach(card; unitCards) card.submitted = delegate() => selectUnit(card.unit); ``` Each `UnitInfoCard` object (which `card` is a member of) contains a `Unit` object called `unit`. The intention of this line was that each object in `unitCards` would call `selectUnit` with it's own `unit` every time it calls `submitted`. Instead, every card calls `submitted` with the *last* value of `card`. Yes, this is because the foreach loop reuses the same memory slot for `card`. Even though this is allocated as a closure, it still only allocates the frame stack of the *enclosing function*, and does not allocate a new slot for each loop iteration. You can force this by using a lambda which allocates the closure: ```d foreach(card; unitCards) card.submitted = (c2) { return () => selectUnit(c2.unit); }(card); ``` This is a lambda which accepts `card` as a parameter, and returns an appropriate delegate. It is important to use a parameter, because if you just use card inside there, it's still using the single stack frame of the calling function! ... I would love to see a solution, but the workaround at least exists! -Steve Well that's something. It's not a very good solution for a language that aims for readability. It took me awhile looking at it to figure out what it is about, as I'm not familiar with this syntax. The solution that I did before seeing this was to add a function to `UnitInfoCard` to give it a delegate with a `Unit unit` parameter, and then that function would give that function with the `unit` parameter set to itself to it's own `submitted` member. I will probably keep it like this for readability. ``` void clickAction(void delegate(Unit) @safe clickAction) { submitted = () => clickAction(unit); } ```
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 16:41:38 UTC, Steven Schveighoffer wrote: This is a very old issue: https://issues.dlang.org/show_bug.cgi?id=2043 since "moved" to https://issues.dlang.org/show_bug.cgi?id=23136 I would love to see a solution, but the workaround at least exists! -Steve Interestingly enough C# used to have the same behaviour but MS decided to go for a breaking change in C# 5; now it behaves as most people expect. Since it's an unsolved problem to keep links working for 10+ years I gave up looking for something official about the subject. Here's an SO question about it though: https://stackoverflow.com/questions/14184515/action-delegate-uses-the-last-values-of-variables-declared-outside-foreach-loop
Re: Why is Phobos `Flag` so overthought ?
Nick Treleaven kirjoitti 8.5.2024 klo 13.24: On Wednesday, 8 May 2024 at 04:27:13 UTC, cc wrote: It doesn't allow a simple boolean to be used as an argument, or any other Flag as they are different instantiations of a template rather than equivalent aliases. It is however awful, cumbersome, annoying design and needs to be completely phased out now that we have named arguments. Flag enforces that the argument says what it relates to. `true` does not say what it relates to. Named arguments are optional, so I don't see how they could make Flag redundant. Well, ```D private struct Undefinable{} auto functionTakingFlags ( int normalArg, Undefinable = Undefinable.init, bool Flag1, Undefinable = Undefinable.init, bool Flag2 ){ // fun body... } ``` As I understand it, this forces the client to use named arguments because they would be trying to pass an `Undefinable` otherwise. They probably could pass `Undefinable` if they really wanted and therefore avoid using named args but they wouldn't do that accidentally. Whether that is any better than the library `Flag` type is up to taste.
Re: Why is Phobos `Flag` so overthought ?
On Wednesday, 8 May 2024 at 04:27:13 UTC, cc wrote: It doesn't allow a simple boolean to be used as an argument, or any other Flag as they are different instantiations of a template rather than equivalent aliases. It is however awful, cumbersome, annoying design and needs to be completely phased out now that we have named arguments. Flag enforces that the argument says what it relates to. `true` does not say what it relates to. Named arguments are optional, so I don't see how they could make Flag redundant.
Re: Why is Phobos `Flag` so overthought ?
On Monday, 6 May 2024 at 17:55:49 UTC, user1234 wrote: I think this just works: ```d enum Flag : bool { no, yes } ``` ... must be a reason but I cant find it RN ;) In "properly" designed Phobos packages, it's unambiguous. Take for example std.datetime.stopwatch: ```d import std.typecons : Flag; alias AutoStart = Flag!"autoStart"; alias MyOtherFlag = Flag!"myOtherFlag"; ... //auto sw = StopWatch(true); // Not allowed //auto sw = StopWatch(MyOtherFlag.yes); // Not allowed auto sw = StopWatch(AutoStart.yes); ``` It doesn't allow a simple boolean to be used as an argument, or any other Flag as they are different instantiations of a template rather than equivalent aliases. It is however awful, cumbersome, annoying design and needs to be completely phased out now that we have named arguments.
Re: TIL: statically initializing an Associative Array
On Tuesday, 7 May 2024 at 01:14:24 UTC, Steven Schveighoffer wrote: On Tuesday, 7 May 2024 at 00:10:27 UTC, Andy Valencia wrote: I had a set of default error messages to go with error code numbers, and did something along the lines of: string[uint] error_text = [ 400: "A message", 401: "A different message" ]; and got "expression is not a constant" ... This was fixed [in 2.106.0](https://dlang.org/changelog/2.106.0.html#dmd.static-assoc-array) please upgrade your compiler. I'm using ldc2 from Debian stable; great news that it's fixed as of late 2023. I'll probably live with my workaround, but it's good to know that it's a bug which has been resolved. Thank you! Andy
Re: TIL: statically initializing an Associative Array
On Tuesday, 7 May 2024 at 00:10:27 UTC, Andy Valencia wrote: I had a set of default error messages to go with error code numbers, and did something along the lines of: string[uint] error_text = [ 400: "A message", 401: "A different message" ]; and got "expression is not a constant" I eventually found this discussion: https://issues.dlang.org/show_bug.cgi?id=6238 I understand that it's problematic, but a message which makes it clearer that compile-time initialization of global AA's are not supported? Because it cost me about a half hour trying to figure out what I was doing wrong. This error message was changed in 2.101.x (unsure which point release): ``` onlineapp.d(1): Error: static initializations of associative arrays is not allowed. onlineapp.d(1):associative arrays must be initialized at runtime: https://dlang.org/spec/hash-map.html#runtime_initialization ``` (My workaround was to initialize the data structure once during app startup.) This was fixed [in 2.106.0](https://dlang.org/changelog/2.106.0.html#dmd.static-assoc-array) please upgrade your compiler. -Steve
Re: TIL: statically initializing an Associative Array
On Tuesday, 7 May 2024 at 01:02:04 UTC, matheus wrote: On Tuesday, 7 May 2024 at 00:10:27 UTC, Andy Valencia wrote: ... Based on what I understood and that issue, I think it was fixed: ... By the way it works as immutable too. Matheus.
Re: TIL: statically initializing an Associative Array
On Tuesday, 7 May 2024 at 00:10:27 UTC, Andy Valencia wrote: I had a set of default error messages to go with error code numbers, and did something along the lines of: string[uint] error_text = [ 400: "A message", 401: "A different message" ]; and got "expression is not a constant" I eventually found this discussion: https://issues.dlang.org/show_bug.cgi?id=6238 I understand that it's problematic, but a message which makes it clearer that compile-time initialization of global AA's are not supported? Because it cost me about a half hour trying to figure out what I was doing wrong. (My workaround was to initialize the data structure once during app startup.) Based on what I understood and that issue, I think it was fixed: import std.stdio; string[uint] aa1 = [1:"ABC",2:"DEF"]; void main(){ auto aa2 = ['A':1,'B':2]; writeln(aa1[1]); writeln(aa1[2]); writeln(aa2['A']); writeln(aa2['B']); } Prints: ABC DEF 1 2 Matheus.
TIL: statically initializing an Associative Array
I had a set of default error messages to go with error code numbers, and did something along the lines of: string[uint] error_text = [ 400: "A message", 401: "A different message" ]; and got "expression is not a constant" I eventually found this discussion: https://issues.dlang.org/show_bug.cgi?id=6238 I understand that it's problematic, but a message which makes it clearer that compile-time initialization of global AA's are not supported? Because it cost me about a half hour trying to figure out what I was doing wrong. (My workaround was to initialize the data structure once during app startup.)
Re: Why is Phobos `Flag` so overthought ?
On Monday, 6 May 2024 at 18:06:53 UTC, Julian Fondren wrote: On Monday, 6 May 2024 at 17:55:49 UTC, user1234 wrote: I think this just works: ```d enum Flag : bool { no, yes } alias AllowVancancy = Flag; // example usage ``` ```d import std.stdio : writeln; enum Flag : bool { no, yes } alias Traditional = Flag; alias Color = Flag; void hello(Traditional traditional, Color color) { if (traditional && color) { writeln("\x1b[31;1mhello world\x1b[0m"); } else if (traditional && !color) { writeln("hello world"); } else if (!traditional && color) { writeln("\x1b[31;1mHello, world!\x1b[0m"); } else { writeln("Hello, world!"); } } void main() { hello(Color.yes, Traditional.yes); // this is wrong, but accepted } ``` Ah yes I see, strongly typed bools. Thanks .
Re: Why is Phobos `Flag` so overthought ?
On Monday, 6 May 2024 at 17:55:49 UTC, user1234 wrote: I think this just works: ```d enum Flag : bool { no, yes } alias AllowVancancy = Flag; // example usage ``` ```d import std.stdio : writeln; enum Flag : bool { no, yes } alias Traditional = Flag; alias Color = Flag; void hello(Traditional traditional, Color color) { if (traditional && color) { writeln("\x1b[31;1mhello world\x1b[0m"); } else if (traditional && !color) { writeln("hello world"); } else if (!traditional && color) { writeln("\x1b[31;1mHello, world!\x1b[0m"); } else { writeln("Hello, world!"); } } void main() { hello(Color.yes, Traditional.yes); // this is wrong, but accepted } ```
Why is Phobos `Flag` so overthought ?
I think this just works: ```d enum Flag : bool { no, yes } alias AllowVancancy = Flag; // example usage ``` Also this is completion friendly whereas Phobos version does not permit DCD completion as it's based on opDispatch. Compare to phobos version: ```d template Flag(string name) { enum Flag : bool { no = false, yes = true } } struct Yes { template opDispatch(string name) { enum opDispatch = Flag!name.yes; } } struct No { template opDispatch(string name) { enum opDispatch = Flag!name.no; } } ``` must be a reason but I cant find it RN ;)
Re: Phobos function to remove all occurances from dynamic array?
On Wednesday, 1 May 2024 at 15:18:03 UTC, Steven Schveighoffer wrote: On Wednesday, 1 May 2024 at 01:09:33 UTC, Liam McGillivray wrote: This is presumably such a common task that I'm surprised it isn't easy to find the answer by searching; Is there a standard library function that removes all elements from a dynamic array that matches an input argument? In `std.array` there's the `replace` function which is supposed to replace all occurrences that match an input with another. It seems to work as described on strings, but I get compiler errors when using it on other array types. I've tried using it to replace occurrences of a certain object in an array with `[]` in order to remove all occurrences, but it's not allowed. Is there a Phobos function that does what I want? It would be crazy if there isn't. `remove` https://dlang.org/phobos/std_algorithm_mutation.html#remove ```d arr = arr.remove!(v => shouldBeRemoved(v)); ``` Why the reassignment? Because `remove` removes elements *in place*, and does not change the range extents. It returns the portion of the range that contains the unremoved elements. So to give an example: ```d auto arr = [1, 2, 3, 4, 5]; auto result = arr.remove!(i => i % 2 == 1); // remove odd elements assert(result == [2, 4]); // first 2 are the slice that is stored in result // the last three are leftovers. assert(arr == [2, 4, 3, 4, 5]); ``` -Steve In case anyone comes upon this in a search, I wanted to point out a couple dangers of using remove. The first is that it mutates arr, as shown in Steve's example. The second is ``` result[0] = 4; assert(result == [4, 4]); assert(arr == [2, 4, 3, 4, 5]); // Fails arr[0] = 2; assert(result == [4, 4]); // Fails ``` Any future changes you make to result or arr change the other. You can use remove to avoid the allocation of a new array, but you better be sure you never read or modify the original array again. If you use filter ``` auto result = arr.filter!(i => i % 2 == 0).array; ``` arr is unchanged and you can use arr and result as you want.
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote: Delegates can be a pain, as they often have results different from what one would intuitively expect. This can easily result in bugs. Here's a line that caused a bug that took me awhile to find: ``` foreach(card; unitCards) card.submitted = delegate() => selectUnit(card.unit); ``` Each `UnitInfoCard` object (which `card` is a member of) contains a `Unit` object called `unit`. The intention of this line was that each object in `unitCards` would call `selectUnit` with it's own `unit` every time it calls `submitted`. Instead, every card calls `submitted` with the *last* value of `card`. Yes, this is because the foreach loop reuses the same memory slot for `card`. Even though this is allocated as a closure, it still only allocates the frame stack of the *enclosing function*, and does not allocate a new slot for each loop iteration. You can force this by using a lambda which allocates the closure: ```d foreach(card; unitCards) card.submitted = (c2) { return () => selectUnit(c2.unit); }(card); ``` This is a lambda which accepts `card` as a parameter, and returns an appropriate delegate. It is important to use a parameter, because if you just use card inside there, it's still using the single stack frame of the calling function! I renamed the inner parameter `c2` to avoid confusion, but you could name it `card` also. Essentially, the stack frame of the inner function is now allocated a closure, and it has it's own reference to `card` as a parameter. This is a very old issue: https://issues.dlang.org/show_bug.cgi?id=2043 since "moved" to https://issues.dlang.org/show_bug.cgi?id=23136 I would love to see a solution, but the workaround at least exists! -Steve
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote: Here's a line that caused a bug that took me awhile to find: ``` foreach(card; unitCards) card.submitted = delegate() => selectUnit(card.unit); ``` I think you can do: ```d import std.algorithm.iteration : each; unitCards.each!(c => c.submitted = () => selectUnit(c.unit)); ```
Re: How can I put the current value of a variable into a delegate?
On Monday, 6 May 2024 at 06:29:49 UTC, Liam McGillivray wrote: This is because the delegate assignment causes the local `card` variable to remain alive. The delegate that's assigned is linked to this variable itself, not the value at the time that the delegate is assigned. This is https://issues.dlang.org/show_bug.cgi?id=23136. Perhaps it can be fixed in the next edition. Is there a way I can dereference a variable when placing it in a delegate, so that it's current value is used, rather than the variable itself? I think you would need to make an array before the loop, assign to an indexed element and use that in the delegate.
How can I put the current value of a variable into a delegate?
Delegates can be a pain, as they often have results different from what one would intuitively expect. This can easily result in bugs. Here's a line that caused a bug that took me awhile to find: ``` foreach(card; unitCards) card.submitted = delegate() => selectUnit(card.unit); ``` Each `UnitInfoCard` object (which `card` is a member of) contains a `Unit` object called `unit`. The intention of this line was that each object in `unitCards` would call `selectUnit` with it's own `unit` every time it calls `submitted`. Instead, every card calls `submitted` with the *last* value of `card`. This is because the delegate assignment causes the local `card` variable to remain alive. The delegate that's assigned is linked to this variable itself, not the value at the time that the delegate is assigned. Is there a way I can dereference a variable when placing it in a delegate, so that it's current value is used, rather than the variable itself?
Re: Show dialog box for uncaught exception (Windows, lld-link)
On Sunday, 5 May 2024 at 18:28:29 UTC, SimonN wrote: My implementation for the message box is now: According to [UTF-8 Everywhere](https://utf8everywhere.org/#windows), I shouldn't use `MessageBoxA` at all. The `A` means ANSI codepages, _not_ UTF-8. My above code _will_ show garbage output when there is some non-ASCII in the exception message. Better: Convert to UTF-16 yourself and call `MessageBoxW`: version (Windows) { import core.sys.windows.windows; import std.conv; const wstring messageBody = wtext(/* ... */, "\0"); MessageBoxW(null, messageBody.ptr, null, MB_ICONERROR); throw /* ... */; } -- Simon
Re: Show dialog box for uncaught exception (Windows, lld-link)
On Sunday, 5 May 2024 at 17:15:10 UTC, Steven Schveighoffer wrote: } catch(Exception e) { visualDisplayOfException(e); throw e; } Thanks! That's practically the same pattern that I already use for logging: Try-catch near the entry point, show the message, re-throw. My implementation for the message box is now: catch (Throwable t) { import core.sys.windows.windows; const string errText = /* ... parse t ... */ MessageBoxA(null, errText.ptr, null, MB_ICONERROR); } That solves my problem. Even though I don't pass my game's window as the parent of the message box (first argument, where I pass `null`), the graphical game halts before exiting, shows the error, and users can screenshot both together. That's good. From your answer, I'll assume: There is no standardized way in the D ecosystem (e.g., by calling a DRuntime function from my usercode) to opt into displaying such a message box for uncaught exceptions. I have to call third-party APIs myself. Or is there something after all? From reading the 2019 thread [Deactivate windows MessageBox dialog on exception](https://forum.dlang.org/post/tlhjypvsaxzymccfc...@forum.dlang.org), it sounds like we should get an error box when we link with `-subsystem:windows`, and no box otherwise. -- Simon
Re: Show dialog box for uncaught exception (Windows, lld-link)
On Sunday, 5 May 2024 at 14:55:20 UTC, SimonN wrote: My application is a graphical game. I close stdout and stderr by passing `-subsystem:windows` to `lld-link` to suppress the extra console window. For a few fatal errors (missing required resources, can't open display, ...), I throw exceptions, log them to logfile, then re-throw them to crash. I can tell Windows users to look in the logfile, but it would be more fitting on Windows to show an error dialog box in addition to the logging. ```d int realMain(string[] args) { // all your normal code goes here } int main(string[] args) { version(Windows) { try { realMain(args); } catch(Exception e) { visualDisplayOfException(e); throw e; } } else { // presumably, non-windows systems shouldn't show a graphical Exception // trace? realMain(args); } } ``` -Steve
Show dialog box for uncaught exception (Windows, lld-link)
Hi, for Windows, I link my executables with `lld-link`, whether for 32-bit and 64-bit and whether I've built with LDC or DMD. How can I generate a dialog box for uncaught exceptions that fly out of my executable's `main()`? When I linked with Optlink years ago for Windows 32-bit, it generated an error dialog box for an uncaught exception. But with `lld-link`, the exception's message lands only on stderr. I didn't see anything related in `lld-link -help`. Can I configure DRuntime in a special way at runtime? My application is a graphical game. I close stdout and stderr by passing `-subsystem:windows` to `lld-link` to suppress the extra console window. For a few fatal errors (missing required resources, can't open display, ...), I throw exceptions, log them to logfile, then re-throw them to crash. I can tell Windows users to look in the logfile, but it would be more fitting on Windows to show an error dialog box in addition to the logging. -- Simon
Re: dlang.org/Learn "hello_world".sort.chain ...
On Tuesday, 26 December 2023 at 10:53:10 UTC, Tony wrote: I just typed in the program that is on the first page of Learn. It has this line: sort(chain(arr1, arr2, arr3)); I assigned that to a variable: arr4 = sort(chain(arr1, arr2, arr3)); then printed it out writefln("%s",arr4); // works and then tried to print out the type of arr4: writefln("%s",typeof(arr4)); and got this error: // HelloWorld.d:25:19: error: cannot pass type SortedRange!(Result, "a < b") as a function argument What exactly is that type? Or maybe, what would it take to understand what that type is? The error message suggests that `SortedRange!(Result, "a < b")` is the type returned by the `sort` function. For additional insights and assistance, you can explore resources like online dissertation help literature review https://literaturereviewwritingservice.com/ This type represents a sorted range of elements, possibly of type `Result`, sorted based on the comparison predicate `"a < b"`. To understand it better, you may need to inspect its definition or consider alternative methods for printing its type.
Re: Turning fixed sized array into tuple
On Saturday, 4 May 2024 at 19:11:14 UTC, Nick Treleaven wrote: On Saturday, 4 May 2024 at 16:58:00 UTC, Dmitry Olshansky wrote: So I have a function: ```d size_t awaitAny(T...)(T args) { ... } ``` And I have: ``d Event*[4] events; `` How do I pass all 4 of events to awaitAny as tuple of arguments? Use `awaitAny(events.tupleof)`? https://dlang.org/spec/arrays.html#array-properties Thanks, totally missed it! — Dmitry Olshansky CEO @ [Glow labs](https://glow-labs.pro) https://olshansky.me
Re: Turning fixed sized array into tuple
On Saturday, 4 May 2024 at 16:58:00 UTC, Dmitry Olshansky wrote: So I have a function: ```d size_t awaitAny(T...)(T args) { ... } ``` And I have: ``d Event*[4] events; `` How do I pass all 4 of events to awaitAny as tuple of arguments? Use `awaitAny(events.tupleof)`? https://dlang.org/spec/arrays.html#array-properties
Turning fixed sized array into tuple
So I have a function: ```d size_t awaitAny(T...)(T args) { ... } ``` And I have: ``d Event*[4] events; `` How do I pass all 4 of events to awaitAny as tuple of arguments? -- Dmitry Olshansky CEO @ [Glow labs](https://glow-labs.pro) https://olshansky.me/about/
Re: Deprecation: foreach: loop index implicitly converted from size_t to int
Well all these proposals to `int` index like `size_t` and `const typeof(arr.length)` are cryptic and less readable and less straightforward in comparison to how it used to be. Feels like horrible decision if the language is suppose to be somewhat futureproof. The `int` was simple, straighforward and great. These suggestions feel like some `C++` all over again.
Re: Goto skipping declarations
On 04/05/2024 8:38 AM, Jonathan M Davis wrote: In any case, I expect that the compiler is just going dumb here because of the label for some reason, and one or more of the checks that it's supposed to be doing is being missed. It is very simple code. A reverse search over the double linked list for the goto from the label. I looked into it fairly recently as an example of type state analysis D is already designed against.
Re: Goto skipping declarations
On Friday, 3 May 2024 at 20:38:31 UTC, Jonathan M Davis wrote: https://issues.dlang.org/show_bug.cgi?id=24535
Re: Goto skipping declarations
On Friday, May 3, 2024 2:38:31 PM MDT Jonathan M Davis via Digitalmars-d-learn wrote: > On Friday, May 3, 2024 1:15:16 PM MDT Ben Jones via Digitalmars-d-learn wrote: > > In general, you can't skip a declaration with goto, but it seems > > to be allowed if the declaration you're skipping is labelled... > > Is that expected or an accepts invalid bug? > > > > https://godbolt.org/z/4qx8Pf6G7 > > > > ```d > > void f1(){ //fails with error about skipping a declaration > > > > int x; > > goto Label; > > int y; > > Label: > > int z; > > > > } > > > > void f2(){ //compiles fine > > > > int x; > > goto Label; > > Dummy: > > int y; > > Label: > > int z; > > > > } > > ``` > > It has to be a bug, and taking it a step further shows that. If you print > out y, you'll get a seemingly random number. E.G. On the first run, I got > > 554440803 > > and on the second I got > > 549310547 > > Presumably, it's a garbage value from whatever happened to be on the stack. > > I'm quite sure that the spec doesn't have anything about being allowed to > skip a declaration just because it has a label on it (honestly, if we _did_ > want that to be the case, the spec would probably be missing it, since it > tends to fall on the side of having too few details rather than too many), > but even if it did, the code is clearly doing something that should not be > happening with initialization without explicitly using = void. So, > _something_ here would nee to be fixed. > > In any case, I expect that the compiler is just going dumb here because of > the label for some reason, and one or more of the checks that it's supposed > to be doing is being missed. Here. I reported it: https://issues.dlang.org/show_bug.cgi?id=24534 - Jonathan M Davis
Re: Goto skipping declarations
On Friday, May 3, 2024 1:15:16 PM MDT Ben Jones via Digitalmars-d-learn wrote: > In general, you can't skip a declaration with goto, but it seems > to be allowed if the declaration you're skipping is labelled... > Is that expected or an accepts invalid bug? > > https://godbolt.org/z/4qx8Pf6G7 > > ```d > void f1(){ //fails with error about skipping a declaration > int x; > goto Label; > int y; > Label: > int z; > } > > void f2(){ //compiles fine > int x; > goto Label; > Dummy: > int y; > Label: > int z; > } > ``` It has to be a bug, and taking it a step further shows that. If you print out y, you'll get a seemingly random number. E.G. On the first run, I got 554440803 and on the second I got 549310547 Presumably, it's a garbage value from whatever happened to be on the stack. I'm quite sure that the spec doesn't have anything about being allowed to skip a declaration just because it has a label on it (honestly, if we _did_ want that to be the case, the spec would probably be missing it, since it tends to fall on the side of having too few details rather than too many), but even if it did, the code is clearly doing something that should not be happening with initialization without explicitly using = void. So, _something_ here would nee to be fixed. In any case, I expect that the compiler is just going dumb here because of the label for some reason, and one or more of the checks that it's supposed to be doing is being missed. - Jonathan M Davis
Goto skipping declarations
In general, you can't skip a declaration with goto, but it seems to be allowed if the declaration you're skipping is labelled... Is that expected or an accepts invalid bug? https://godbolt.org/z/4qx8Pf6G7 ```d void f1(){ //fails with error about skipping a declaration int x; goto Label; int y; Label: int z; } void f2(){ //compiles fine int x; goto Label; Dummy: int y; Label: int z; } ```