Re: Operator "+=" overloading for class?
On Sunday, 17 December 2023 at 04:13:20 UTC, Ki Rill wrote: auto opOpAssign(string op)(in ElementType rhs) { mixin("return this" ~ op ~ "rhs;"); } ``` check what `op` is. pretty sure it is "+" not "+=" so your element isnt' saved anywhere. also a bit iffy there isn't a member here to work on
Re: Operator "+=" overloading for class?
On Sunday, 17 December 2023 at 04:15:02 UTC, Ki Rill wrote: On Sunday, 17 December 2023 at 04:13:20 UTC, Ki Rill wrote: I am trying to overload `opOpAssign` for my class. The code [...] I forgot to mention, it is relevant to [`Value`](https://github.com/rillki/tiny-grad/blob/main/source/rk/tgrad/core/value.d) class only. This unittest fails: ```d // test opOpAssign auto g = value(0); g += value(3); assert(g.data == 3); ```
Re: Operator "+=" overloading for class?
On Sunday, 17 December 2023 at 04:13:20 UTC, Ki Rill wrote: I am trying to overload `opOpAssign` for my class. The code [...] I forgot to mention, it is relevant to [`Value`](https://github.com/rillki/tiny-grad/blob/main/source/rk/tgrad/core/value.d) class only.
Operator "+=" overloading for class?
I am trying to overload `opOpAssign` for my class. The code compiles, but it does not seem to be working. ```d // binary operations have already been implemented for Value // i need +=, -=, *=, /= auto opOpAssign(string op)(Value rhs) { mixin("return this" ~ op ~ "rhs;"); } auto opOpAssign(string op)(in ElementType rhs) { mixin("return this" ~ op ~ "rhs;"); } ``` What am I missing here? Full project code can be found [here](https://github.com/rillki/tiny-grad).
Re: Changing behavior of associative array
On Sunday, 17 December 2023 at 00:10:56 UTC, Kevin Bailey wrote: instead it seems like 'm' is a pointer to a std::map, that is initialized on use if null. (I think it's that latter part that gives the illusion of being already initialized.) Yes: https://dlang.org/spec/hash-map.html#construction_and_ref_semantic
Re: Changing behavior of associative array
On Saturday, 16 December 2023 at 22:44:16 UTC, Dennis wrote: That's because `m[f] = 1` initializes the associative array to something non-null. If you pass a `null` AA to a function which adds things, the caller will still have a null pointers. You can initialize a non-null empty AA like this: ```D uint[Foo] m = new uint[Foo]; ``` Then, `m` can be passed by value and you can make additions or removals which the caller sees, unless you assign a new AA in the function. Thanks Dennis. I'll have to tweak my mental model of what's happening. I was picturing a std::map-like thing that was passed by reference, but instead it seems like 'm' is a pointer to a std::map, that is initialized on use if null. (I think it's that latter part that gives the illusion of being already initialized.)
Re: Changing behavior of associative array
On Saturday, 16 December 2023 at 22:44:16 UTC, Dennis wrote: That's because `m[f] = 1` initializes the associative array to something non-null. If you pass a `null` AA to a function which adds things, the caller will still have a null pointers. I've gotten this error in deployed Perl. Whenever the ceremony of creating a data structure is reduced, people can lose sight of when that happens. Here's a less common gotcha: ```d void main() { import std.stdio : writeln; int force_realloc(ref int[] seq) { foreach (int i; 1 .. 1_000_000) { seq ~= i; } return 1234; } int[] a = [4321]; writeln(a[0]); // 4321, of course a[0] = force_realloc(a); writeln(a[0]); // still 4321 } ``` The `a[0]` on the left of the assignment is decided early, and then force_realloc() changes what the location should be.
Re: Changing behavior of associative array
On Saturday, 16 December 2023 at 21:30:55 UTC, kdevel wrote: If you comment out this line ``` //m[f] = 1; ``` in your main function of your posted code you can catch up with your real programm insofar as you now need a ref parameter here, too. That's because `m[f] = 1` initializes the associative array to something non-null. If you pass a `null` AA to a function which adds things, the caller will still have a null pointers. You can initialize a non-null empty AA like this: ```D uint[Foo] m = new uint[Foo]; ``` Then, `m` can be passed by value and you can make additions or removals which the caller sees, unless you assign a new AA in the function.
Re: now I need -allinst when dmd compiles the unittest
On Tuesday, 5 December 2023 at 03:36:04 UTC, Steven Schveighoffer wrote: Are you using -checkaction=context? Right. [...] For reference: https://issues.dlang.org/show_bug.cgi?id=22374 https://issues.dlang.org/show_bug.cgi?id=22902 https://issues.dlang.org/show_bug.cgi?id=19937 You even reported one of these... Thanks for reminding me of these unfixed errors. Wouldn't it be advisable to automatically invoke -allinst whenever -checkaction=context is encountered?
Re: Changing behavior of associative array
On Saturday, 16 December 2023 at 20:04:54 UTC, Kevin Bailey wrote: I've added a TON of writeln's to confirm this. The *instant* I made the parameter "ref", the real program starts acting as expected, and the print-outs show the correct results. If you comment out this line ``` //m[f] = 1; ``` in your main function of your posted code you can catch up with your real programm insofar as you now need a ref parameter here, too. Does anyone know why the behavior would change? Has anyone seen anything like this? Sure.
Changing behavior of associative array
Perhaps someone can help solve this mystery. I have a sample program that adds structs to an associative array (as keys) in a subroutine. The program passes the array by reference as expected (below). My real program does the same thing and yet the associative array is passed by value. Thus anything added in the subroutine is lost. I've added a TON of writeln's to confirm this. The *instant* I made the parameter "ref", the real program starts acting as expected, and the print-outs show the correct results. Does anyone know why the behavior would change? Has anyone seen anything like this? I even tried importing the same libraries into both programs. The only remaining difference is that the real function has several more arguments (7), but I would be shocked if D changed its behavior because of that. thx ``` import std.stdio; struct Foo { uint a, b, c; } void add_one_and_recurse( uint[Foo] m, int x) { if (!x) return; foreach (k,v; m) // Prints the 1 from main() writeln(k, ", ", v); // as expected. add_one_and_recurse(m, x-1); Foo f = {4, 5, x}; m[f] = 7; } int main() { uint[Foo] m; Foo f = {1, 2, 3}; m[f] = 1; add_one_and_recurse(m, 3); foreach (k,v; m) // Prints 4 items writeln(k, ", ", v); // as expected. return 0; } ```