How is opEquals used in toHash
In the solution to one of the exercises in Programming in D the unittests fail with respect to the toHash implementation. Here is a link to the full solution provided: https://run.dlang.io/gist/99ddf791f86aaa9d333d032166aadcb9?args=-unittest%20-main and the link to the relevant section in the book: https://ddili.org/ders/d.en/object.html so while the unittest for equality passes, the next test with `in` is where the failure occurs: ```D // ... assert(area1 == area2);// Passes double[TriangularArea] areas; areas[area1] = 1.25; assert(area2 in areas); // Fails // ... ``` the issue must be with the toHash function given ``` D override size_t toHash() const { /* Since the 'points' member is an array, we can take * advantage of the existing toHash algorithm for * array types. */ return typeid(points).getHash(); } ``` I looked into the object library documentation and saw that the template getHash calls hashOf which calls core.internal.hash.hashOf etc. But what I do not understand is why opEquals is necessary and where in the implementation of toHash it plays its role? Since area1 and area2 have different static arrays of Points I understand why `typeid(points).getHash()` would produce different values for each, but it seems like the opEquals should play a part in making them produce the same hash.
Re: ref struct member function
On Thursday, 13 May 2021 at 19:48:44 UTC, Ali Çehreli wrote: I was writing this example that shows a use case for the problem (marked with BUG below): ```D struct Fraction { auto n = 0L; auto d = 1L; // ... other bits ... ref Fraction reduce() { import std.numeric : gcd; // v = gcd(n, d); // if (v > 1) { // n /= v; // d /= v; // } return this; } // ... etc ... } ref foo() { import std.stdio : writeln; auto f = Fraction(3, 9); // BUG: Returns reference to an object on the stack return f.reduce(); } void main() { // Refers to a temporary (it would be a copy without the &) auto f = (); // Do some unrelated things hoping that space for dead objects on // the stack will be reused. import std.stdio; import std.random; writeln("doing something else: ", uniform(0, 6)); writeln(f.d); // Access dead and overwritten object (does NOT print // 9 on my system) } ``` Putting 'return' where Steve shows makes the compiler guard us against this misuse and the program thankfully does not compile. Ali Hi thank you both for your answers. I had understood from an earlier chapter how this could introduce a bug, but I was confused because the warning suggests attaching ```return``` to the parameter, which is empty in the declaration. So my next question would be how come ref based operator overloads are not labelled as return and do not show this warning? ``` D struct Fraction { auto n = 0L; auto d = 1L; ref Fraction opUnary(string op)() if (op == "++") { n += d; return this; } } ref Fraction foo() { auto f = Fraction(1, 3); // Same bug as with reduce return ++f; } ```
ref struct member function
Hi I am working through Programming in D. In one exercise I have a helper function in a struct ```D struct Fraction { auto n = 0L; auto d = 1L; // ... other bits ... ref Fraction reduce() { import std.numeric : gcd; v = gcd(n, d); if (v > 1) { n /= v; d /= v; } return this; } // ... etc ... } void main() { import std.stdio : writeln; auto f = Fraction(3, 9); writeln(f.reduce()); } ``` This works but issues a deprecation warning: ``` onlineapp.d(30): Deprecation: returning `this` escapes a reference to parameter `this` onlineapp.d(30):perhaps annotate the parameter with `return` Fraction(1, 3) ``` I found several other ways to make this work without the warnings, but I am wondering how to make this particular case work, or if it is not a recommended way, what the proper way would be.
Calling readln() after readf
I didn't want to necropost, but I ran into the same behaviour as in this post: https://forum.dlang.org/post/yfybveovbknvvxmio...@forum.dlang.org and was just curious to understand it better. If I call readln() after having previously called readf(), it does not behave as expected: ```d import std.stdio, std.string; void main() { write("Please enter a number: "); double number; readf(" %s", number); write("Please enter a string: "); string input = strip(readln()); writefln!("number: %s --- string: %s")(number, input); } ``` Gives me the following: ``` Please enter a number: 1 Please enter a string: number: 1 string: ``` I know I can get this to work replacing the `strin(readln())` with `readf(" %s\n", input)`, but I also found if I just call `strip(readln())` an extra time this worked as well, but what is confusing to me is if I have multiple readf's I still only need to call readln one extra time to get it to work as expected: ```d import std.stdio, std.string; void main() { write("Please enter a number: "); double number1; readf(" %s", number1); write("Please enter a number: "); double number2; readf(" %s", number2); // Handle what should be two \n's from readf? string input = strip(readln()); // Continue as normal write("Please enter a string: "); input = strip(readln()); writefln!("number1: %s --- number2: %s --- string: %s") (number1, number2, input); } ``` And this works. ``` Please enter a number: 1 Please enter a number: 2 Please enter a string: hello number1: 1 --- number2: 2 --- string: hello ``` Could anyone help explain this to me, and also is there a better way to handle this when wanting to use a mix of readf and readln?