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 ?
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: 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: 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 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.
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?