Nice example for operator overload resulting in readable linear algebra expressions
I just want to share a view lines of code. The availability of operator overloading can result in very short and precise code for linear algebra. To test/explore it a little I just modified the alias this example: ``` #!/usr/bin/env rdmd struct Point { double[2] p; // Forward all undefined symbols to p alias p this; auto opBinary(string op)(Point rhs) { static if (op == "+") { Point ret; ret[0] = p[0] + rhs.p[0]; ret[1] = p[1] + rhs.p[1]; return ret; } else static if (op == "-") { Point ret; ret[0] = p[0] - rhs.p[0]; ret[1] = p[1] - rhs.p[1]; return ret; } else static if (op == "*") return p[0] * rhs.p[0] + p[1] * rhs.p[1]; else static assert(0, "Operator " ~ op ~ " not implemented"); } } void main() { import std.stdio;// : writefln,write; // Point behaves like a `double[2]` ... Point p1, p2; p1 = [2, 1], p2 = [1, 1]; // ... but with extended functionality writef("p1*(p1 + p2) = %s*(%s + %s) =", p1, p1, p2); write(p1 * (p1 + p2)); // compare this to code without operator overload: } ``` Compare: ``p1 * (p1 + p2)`` to something with a structure like ``dot(p1,(add(p1,p2)).`` (With the Dlangs UFCS it might become: ``p1.dot(p1.add(p2))`` )
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 06:18:33 UTC, mw wrote: Now, how to convert it to a native array: double[] row = record; Error: cannot implicitly convert expression record of type Tuple!(double, double, double, ..., double) to double[] (I know for tuple, we can do: double[] arr = [record];) double[] row = [record.expand];
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 04:38:07 UTC, Paul Backus wrote: On Monday, 7 December 2020 at 04:03:05 UTC, mw wrote: So my next question: given N, how do I create a Tuple!(double, double, ... n-double) type programmatically? import std.meta: Repeat; alias NDoubles = Tuple!(Repeat!(N, double)); Note that N must be a compile-time constant, since the number of elements in a Tuple is fixed at compile time. Yes, I just realized that Tuple (upper T, compile time) and tuple (lower t) are different things. Now, how to convert it to a native array: double[] row = record; Error: cannot implicitly convert expression record of type Tuple!(double, double, double, ..., double) to double[] (I know for tuple, we can do: double[] arr = [record];)
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 04:03:05 UTC, mw wrote: So my next question: given N, how do I create a Tuple!(double, double, ... n-double) type programmatically? import std.meta: Repeat; alias NDoubles = Tuple!(Repeat!(N, double)); Note that N must be a compile-time constant, since the number of elements in a Tuple is fixed at compile time.
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 03:51:02 UTC, Paul Backus wrote: On Monday, 7 December 2020 at 02:25:23 UTC, mw wrote: onlineapp.d(8): Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar) should `r`'s type be integer array? and how do I access each elelment of the row? Thanks. The docs [1] say that csvReader returns an input range, not an array. Input ranges don't support indexing, only iteration (e.g. with `foreach`). If you want an array, you will have to use `std.array.array` to create one. [1] http://phobos.dpldocs.info/std.csv.csvReader.1.html Thanks. I saw the 1st example on this page: https://dlang.org/phobos/std_csv.html foreach (record; csvReader!(Tuple!(string, string, int))(text)) { writefln("%s works as a %s and earns $%d per year", record[0], record[1], record[2]); } So my next question: given N, how do I create a Tuple!(double, double, ... n-double) type programmatically?
Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
On Monday, 7 December 2020 at 02:25:23 UTC, mw wrote: onlineapp.d(8): Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar) should `r`'s type be integer array? and how do I access each elelment of the row? Thanks. The docs [1] say that csvReader returns an input range, not an array. Input ranges don't support indexing, only iteration (e.g. with `foreach`). If you want an array, you will have to use `std.array.array` to create one. [1] http://phobos.dpldocs.info/std.csv.csvReader.1.html
how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)
Hi, I'm trying this code: i.e. print out the 1st element of each row https://run.dlang.io/is/pG921a void main() { import std.csv; import std.stdio: write, writeln, writef, writefln; import std.algorithm.comparison : equal; string text = "76,26,22"; auto records = text.csvReader!int; foreach(r; records) {writeln(r[0]);} // line 8 assert(records.equal!equal([ [76, 26, 22], ])); } but I got a compile error: onlineapp.d(8): Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar) should `r`'s type be integer array? and how do I access each elelment of the row? Thanks.
Re: operator overload for sh-like scripting ?
On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote: eg Sh(echo) < "meh"; struct Sh { // you see the idea we have op overload for < here } You can't overload < separately - all the comparison operators (<, <=, >, >=) are handled via opCmp. Even if you choose to go down that route, there are other issues - opCmp needs to return something that may be compared to 0, since (a < b) is rewritten as (a.opCmp(b) < 0), and the compiler checks if you are simply discarding the return value of a comparison, so all in all, you shouldn't do that in D (and the hoops you have to jump through to make it work makes the code a lot less readable): struct Sh { int opCmp(string s) { import std.stdio : writeln; writeln(s); return 0; } } unittest { Sh sh; auto _ = sh < "baz"; } This is also not chainable, so something like (sh < "foo" < "bar") won't work, even with parentheses. There's also the issue of (a < b) having a defined meaning in D (a less than b), and such overloading leads to code that may be less readable. This is a point with differing opinions, and I'm not firmly on either side of that argument, but it's worth pointing out. Now, if you absolutely want something that's somewhat similar in regular D code, there's <<: struct Sh { Sh opBinary(string op : "<<")(string s) { import std.stdio : writeln; writeln(s); return this; } } unittest { Sh sh; sh << "foo" << "bar"; } While this works, it's a design choice that C++ has gotten a lot of flak for, including one of my favorite C++ quotes: "I saw 'cout' being shifted 'Hello world' times to the left and stopped right there." There are cases where it's not at obvious to the reader of the code what's happening, so such operator overloading should be used with caution. A better choice, perhaps, if using < is important, would be to use a DSL and have it obvious in the code that normal D rules aren't at play: void fun() { Sh sh; mixin dsl!` sh < "foo"; `; } At this point though, you're looking at a considerable chunk of code just for a bit of syntactic sugar. -- Simen
Re: operator overload for sh-like scripting ?
On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote: Sh(echo) < "meh"; Not allowed in D - it only does a comparison overload which covers < and > (and <= and >=). Though we could do strings and stuff. especially with my string interpolation dip https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f we could make it work quite well!
operator overload for sh-like scripting ?
eg Sh(echo) < "meh"; struct Sh { // you see the idea we have op overload for < here }
Re: no [] operator overload for type Chunks!(char[])
On 5/30/18 5:41 PM, Malte wrote: On Wednesday, 30 May 2018 at 21:27:44 UTC, Ali Çehreli wrote: On 05/30/2018 02:19 PM, Malte wrote: Why does this code complain at the last line about a missing [] operator overload? auto buffer = new char[6]; auto chunked = buffer.chunks(3); chunked[1][2] = '!'; Same happens with wchar. Dchar and byte work as expected. UTF-8 auto decoding strikes again. :) Even though the original container is char[], passing it through Phobos algorithms generated range of dchar. The thing is, those dchar elements are generated (decoded from chars) "on the fly" as one iterates over the range. Which means, there is no array of dchar to speak of, so there is no random access. I see. Not what I would have expected, but makes sense for people working with UTF-8 strings. Thanks for the fast answer. You can use byCodeUnit to turn it back into an indexable range: auto chunked = buffer.byCodeUnit.chunks(3); -Steve
Re: no [] operator overload for type Chunks!(char[])
On Wednesday, 30 May 2018 at 21:27:44 UTC, Ali Çehreli wrote: On 05/30/2018 02:19 PM, Malte wrote: Why does this code complain at the last line about a missing [] operator overload? auto buffer = new char[6]; auto chunked = buffer.chunks(3); chunked[1][2] = '!'; Same happens with wchar. Dchar and byte work as expected. UTF-8 auto decoding strikes again. :) Even though the original container is char[], passing it through Phobos algorithms generated range of dchar. The thing is, those dchar elements are generated (decoded from chars) "on the fly" as one iterates over the range. Which means, there is no array of dchar to speak of, so there is no random access. Ali I see. Not what I would have expected, but makes sense for people working with UTF-8 strings. Thanks for the fast answer.
Re: no [] operator overload for type Chunks!(char[])
On 05/30/2018 02:19 PM, Malte wrote: Why does this code complain at the last line about a missing [] operator overload? auto buffer = new char[6]; auto chunked = buffer.chunks(3); chunked[1][2] = '!'; Same happens with wchar. Dchar and byte work as expected. UTF-8 auto decoding strikes again. :) Even though the original container is char[], passing it through Phobos algorithms generated range of dchar. The thing is, those dchar elements are generated (decoded from chars) "on the fly" as one iterates over the range. Which means, there is no array of dchar to speak of, so there is no random access. Ali
no [] operator overload for type Chunks!(char[])
Why does this code complain at the last line about a missing [] operator overload? auto buffer = new char[6]; auto chunked = buffer.chunks(3); chunked[1][2] = '!'; Same happens with wchar. Dchar and byte work as expected.
Re: operator overload
On Tuesday, 12 December 2017 at 17:13:55 UTC, Biotronic wrote: On Tuesday, 12 December 2017 at 16:54:17 UTC, Biotronic wrote: There is no way in C++ to set the format the way you want it. If you want binary output, you need to call a function like your binario function. Of course this is not entirely true - there is a way, but it's ugly and probably not what you want: struct BinStream { std::ostream& os; BinStream(std::ostream& os) : os(os) {} template BinStream& operator<<(T&& value) { os << value; return *this; } BinStream& operator<<(int value) { os << binario(value); return *this; } std::ostream& operator<<(std::ios_base& (__cdecl *_Pfn)(std::ios_base&)) { return os << _Pfn; } }; struct Bin { friend BinStream operator<<(std::ostream& os, const Bin& f); } bin; BinStream operator<<(std::ostream& os, const Bin& f) { return BinStream(os); } int main() { std::cout << "\n\t127 em binario: " << binario(127) << "\n\t127 em binario: " << bin << 127 << "\n\t127 em octal: " << std::oct << 127 << "\n\t127 em binario: " << bin << 127 << "\n\t127 em hexadecimal: " << std::hex << 127 << "\n\t127 em binario: " << bin << 127 << "\n\t127 em decimal: " << std::dec << 127 << "\n\t127 em binario: " << bin << 127 << "\n\n"; } What is this black magic? Instead of overriding how std::ostream does formatting, Bin::Operator<< now returns a wrapper around a std::ostream, which special cases ints. If it gets any other format specifiers, it returns the ostream again, and the binary formatting is gone. All in all, I think the conclusion is: Stay with D. -- Biotronic I tried to execute with this part of the code std::ostream& operator<<(std::ios_base& (__cdecl *_Pfn)(std::ios_base&)) { return os <<_Pfn; } and it returns me this error below what is the include? bin2.cxx:44:43: error: expected ‘,’ or ‘...’ before ‘(’ token std::ostream& operator<<(std::ios_base& (__cdecl *_Pfn)(std::ios_base&)) ^ bin2.cxx: In member function ‘std::ostream& BinStream::operator<<(std::ios_base&)’: bin2.cxx:46:16: error: ‘_Pfn’ was not declared in this scope return os <<_Pfn;
Re: operator overload
On Tuesday, 12 December 2017 at 17:13:55 UTC, Biotronic wrote: On Tuesday, 12 December 2017 at 16:54:17 UTC, Biotronic wrote: There is no way in C++ to set the format the way you want it. If you want binary output, you need to call a function like your binario function. Of course this is not entirely true - there is a way, but it's ugly and probably not what you want: struct BinStream { std::ostream& os; BinStream(std::ostream& os) : os(os) {} template BinStream& operator<<(T&& value) { os << value; return *this; } BinStream& operator<<(int value) { os << binario(value); return *this; } std::ostream& operator<<(std::ios_base& (__cdecl *_Pfn)(std::ios_base&)) { return os << _Pfn; } }; struct Bin { friend BinStream operator<<(std::ostream& os, const Bin& f); } bin; BinStream operator<<(std::ostream& os, const Bin& f) { return BinStream(os); } int main() { std::cout << "\n\t127 em binario: " << binario(127) << "\n\t127 em binario: " << bin << 127 << "\n\t127 em octal: " << std::oct << 127 << "\n\t127 em binario: " << bin << 127 << "\n\t127 em hexadecimal: " << std::hex << 127 << "\n\t127 em binario: " << bin << 127 << "\n\t127 em decimal: " << std::dec << 127 << "\n\t127 em binario: " << bin << 127 << "\n\n"; } What is this black magic? Instead of overriding how std::ostream does formatting, Bin::Operator<< now returns a wrapper around a std::ostream, which special cases ints. If it gets any other format specifiers, it returns the ostream again, and the binary formatting is gone. All in all, I think the conclusion is: Stay with D. -- Biotronic I understand is basically this now I will see the necessity of this basically the example I wanted to do is to understand how it would be done in the most correct way, now I will study to do other cases if nescessarios but primarily is to convert only integers but you did exactly the that I wanted I did some studies in the D language and it already has a way to convert to binary without any work just using% b as in printf you use% X or% x to convert to exa ... and that was the reason that made me interested in understand this was looking at some older glibc and the way printf understands these very interesting conversion operators
Re: operator overload
On Tuesday, 12 December 2017 at 16:54:17 UTC, Biotronic wrote: There is no way in C++ to set the format the way you want it. If you want binary output, you need to call a function like your binario function. Of course this is not entirely true - there is a way, but it's ugly and probably not what you want: struct BinStream { std::ostream& os; BinStream(std::ostream& os) : os(os) {} template BinStream& operator<<(T&& value) { os << value; return *this; } BinStream& operator<<(int value) { os << binario(value); return *this; } std::ostream& operator<<(std::ios_base& (__cdecl *_Pfn)(std::ios_base&)) { return os << _Pfn; } }; struct Bin { friend BinStream operator<<(std::ostream& os, const Bin& f); } bin; BinStream operator<<(std::ostream& os, const Bin& f) { return BinStream(os); } int main() { std::cout << "\n\t127 em binario: " << binario(127) << "\n\t127 em binario: " << bin << 127 << "\n\t127 em octal: " << std::oct << 127 << "\n\t127 em binario: " << bin << 127 << "\n\t127 em hexadecimal: " << std::hex << 127 << "\n\t127 em binario: " << bin << 127 << "\n\t127 em decimal: " << std::dec << 127 << "\n\t127 em binario: " << bin << 127 << "\n\n"; } What is this black magic? Instead of overriding how std::ostream does formatting, Bin::Operator<< now returns a wrapper around a std::ostream, which special cases ints. If it gets any other format specifiers, it returns the ostream again, and the binary formatting is gone. All in all, I think the conclusion is: Stay with D. -- Biotronic
Re: operator overload
On Tuesday, 12 December 2017 at 15:52:09 UTC, dark777 wrote: I know that this community is not of c ++, but some time I have been studying how to do overload of ostream operators in c ++ and I even managed to get to this result but the same is not converting to binary only presents zeros as output to any number already tried to pass parameter of variable and yet he is not getting the number for conversion how to solve it so that it works correctly? PS: if I use the same conversion algorithm in a function it converts normally it is not only converting to the output of the operator .. https://pastebin.com/BXGXiiRk This line: << "\n\t127 em binario: " << bin << 127 << "\n\n"; Your hope is that the '<< bin' part should behave just like std::hex does, except binary instead of hex. Right? I'm afraid that's not how C++ formatting works. You can see a hint of what happens in the output you get: 127 em binario: 127 The zeroes are from the uninitialized int in your Bin struct, and the '127' is from the 127 you pass right after passing bin. Translating to code that does not use operators, the behavior you expect is something like this: std::cout.print("\n\t127 em binario: "); std::cout.setFormat(bin); std::cout.print(127); // Should use bin for formatting std::cout.print("\n\n"); The actual behavior is something like this: std ::cout.print("\n\t127 em binario: "); std::cout.print(bin); // Prints the value stored in bin. That is, 0. std::cout.print(127); // Prints 127 just the way it would otherwise print it. std::cout.print("\n\n"); There is no way in C++ to set the format the way you want it. If you want binary output, you need to call a function like your binario function. The point of overloading operator<<(std::ostream&, MyType) is not to format another type, but to be able to print MyType in a given way. Basically like toString() in D, C# or Java. -- Biotronic
operator overload
I know that this community is not of c ++, but some time I have been studying how to do overload of ostream operators in c ++ and I even managed to get to this result but the same is not converting to binary only presents zeros as output to any number already tried to pass parameter of variable and yet he is not getting the number for conversion how to solve it so that it works correctly? PS: if I use the same conversion algorithm in a function it converts normally it is not only converting to the output of the operator .. https://pastebin.com/BXGXiiRk
Re: operator overload for enum
On 10.06.2016 13:02, Satoshi wrote: Hello, why operator overloading is not working as a static methods through the UFCS? ... It's an arbitrary limitation. https://issues.dlang.org/show_bug.cgi?id=8062 (The specification has been updated in the meantime, it now documents the limitation explicitly. https://dlang.org/spec/operatoroverloading.html) I need overload a << operator in this way: enum PlatformID { None, Trinix, Unix, MacOS, Windows } PlatformID toPlatformID(string platform) { switch (platform.toLower()) { case "trinix": return PlatformID.Trinix; case "unix":return PlatformID.Unix; case "macos": return PlatformID.MacOS; case "windows": return PlatformID.Windows; default:return PlatformID.None; } } void opBinary(string op)(ref PlatformID plat, auto ref const string str) if (op == "<<") { plat = toPlatformID(str); } void thisIsTest() { PlatformID id; id << "x86_64"; // this is not working id.opBinary!("<<")("test"); // but this works O.K. } Yuck. This should at the very least be opAssign instead.
operator overload for enum
Hello, why operator overloading is not working as a static methods through the UFCS? I need overload a << operator in this way: enum PlatformID { None, Trinix, Unix, MacOS, Windows } PlatformID toPlatformID(string platform) { switch (platform.toLower()) { case "trinix": return PlatformID.Trinix; case "unix":return PlatformID.Unix; case "macos": return PlatformID.MacOS; case "windows": return PlatformID.Windows; default:return PlatformID.None; } } void opBinary(string op)(ref PlatformID plat, auto ref const string str) if (op == "<<") { plat = toPlatformID(str); } void thisIsTest() { PlatformID id; id << "x86_64"; // this is not working id.opBinary!("<<")("test"); // but this works O.K. }
Re: What's wrong in this templatized operator overload ?
On Thursday, 22 October 2015 at 05:17:29 UTC, Cauterite wrote: On Thursday, 22 October 2015 at 04:25:01 UTC, MobPassenger wrote: On Thursday, 22 October 2015 at 04:01:16 UTC, Mike Parker wrote: On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger wrote: code: --- struct Foo { bool opIn_r(T)(T t){return false;} } This needs to be marked with const: struct Foo { bool opIn_r(T)(T t) const {return false;} } what's the rationale ? what's guaranteed by the qualifier that's not already true without const ? `const` just means the function won't mutate the object. `const` functions can be safely called on mutable, const and immutable objects. Non-`const` functions can only be called on mutable objects. Thx for the explanations. By the way I knew that when const is applied to the return type it has to be surrounded between parens but so far I've never encountered the other case...And now I also remember why this attribte should rather be put at the right of the function declaration.
Re: What's wrong in this templatized operator overload ?
On Thursday, 22 October 2015 at 04:01:16 UTC, Mike Parker wrote: On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger wrote: code: --- struct Foo { bool opIn_r(T)(T t){return false;} } This needs to be marked with const: struct Foo { bool opIn_r(T)(T t) const {return false;} } what's the rationale ? what's guaranteed by the qualifier that's not already true without const ?
Re: What's wrong in this templatized operator overload ?
On Thursday, 22 October 2015 at 04:25:01 UTC, MobPassenger wrote: On Thursday, 22 October 2015 at 04:01:16 UTC, Mike Parker wrote: On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger wrote: code: --- struct Foo { bool opIn_r(T)(T t){return false;} } This needs to be marked with const: struct Foo { bool opIn_r(T)(T t) const {return false;} } what's the rationale ? what's guaranteed by the qualifier that's not already true without const ? `const` just means the function won't mutate the object. `const` functions can be safely called on mutable, const and immutable objects. Non-`const` functions can only be called on mutable objects.
Re: What's wrong in this templatized operator overload ?
On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger wrote: code: --- struct Foo { bool opIn_r(T)(T t){return false;} } This needs to be marked with const: struct Foo { bool opIn_r(T)(T t) const {return false;} }
Re: What's wrong in this templatized operator overload ?
On Thursday, 22 October 2015 at 03:21:35 UTC, MobPassenger wrote: On Thursday, 22 October 2015 at 03:18:25 UTC, MobPassenger wrote: code: Plz don't reply, there's been a forum bug while posting. What forum bug would that be?
What's wrong in this templatized operator overload ?
code: --- struct Foo { bool opIn_r(T)(T t){return false;} } static immutable Foo foo; // ouch //static Foo foo; // OK void main() { assert("a" !in foo); } --- output: --- Error: template Foo.opIn_r cannot deduce function from argument types !()(string) immutable, candidates are: runnable.Foo.opIn_r(T)(T t) ---
What's wrong in this templatized operator overload ?
code: --- struct Foo { bool opIn_r(T)(T t){return false;} } static immutable Foo foo; // ouch //static Foo foo; // OK void main() { assert("a" !in foo); }
Re: What's wrong in this templatized operator overload ?
On Thursday, 22 October 2015 at 03:18:25 UTC, MobPassenger wrote: code: Plz don't reply, there's been a forum bug while posting. Full post is here: http://forum.dlang.org/thread/kaqyeiakjunqoexos...@forum.dlang.org
Does it make sense to add attribute to operator overload functions ?
Everything is in the Q. I ask this because those functions are hidden behind symbols and keywords (+=, ~, in, etc.). It's not that obvious for a user who would write a custom type. e.g: --- struct myType { @safe nothrow opIndexAssign(t1 paramValue,t2 paramIndex){} } --- are the attributes necessary ? Are opXXX functions handled just like any other functs ? (traversal compat. of the attribs)
Re: Does it make sense to add attribute to operator overload functions ?
On Saturday, 25 October 2014 at 17:14:51 UTC, Jkpl wrote: Everything is in the Q. I ask this because those functions are hidden behind symbols and keywords (+=, ~, in, etc.). It's not that obvious for a user who would write a custom type. e.g: --- struct myType { @safe nothrow opIndexAssign(t1 paramValue,t2 paramIndex){} } --- are the attributes necessary ? Are opXXX functions handled just like any other functs ? (traversal compat. of the attribs) In every aspect they are ordinary functions, except they each have an additional unique way of being called (the relevant operator syntax). In short, yes.
Re: Does it make sense to add attribute to operator overload functions ?
On Saturday, 25 October 2014 at 18:38:12 UTC, John Colvin wrote: On Saturday, 25 October 2014 at 17:14:51 UTC, Jkpl wrote: Everything is in the Q. I ask this because those functions are hidden behind symbols and keywords (+=, ~, in, etc.). It's not that obvious for a user who would write a custom type. e.g: --- struct myType { @safe nothrow opIndexAssign(t1 paramValue,t2 paramIndex){} } --- are the attributes necessary ? Are opXXX functions handled just like any other functs ? (traversal compat. of the attribs) In every aspect they are ordinary functions, except they each have an additional unique way of being called (the relevant operator syntax). In short, yes. Thx, A bit less confused by them now.
template operator overload
Just out of curiosity: Is it possible to call an overloaded operator with a template type? import std.stdio; struct A { void opIndex(T)(size_t index) { } } void main() { A a; a.opIndex!int(0); // [1] a!int[0]; // [2] } [1] works, but [2] fails. How can I call opIndex with bracket syntax and a typename? Or is this not possible?
Re: template operator overload
On 2013-11-27 16:07:50 +, Namespace said: Just out of curiosity: Is it possible to call an overloaded operator with a template type? import std.stdio; struct A { void opIndex(T)(size_t index) { } } void main() { A a; a.opIndex!int(0); // [1] a!int[0]; // [2] } [1] works, but [2] fails. How can I call opIndex with bracket syntax and a typename? Or is this not possible? You need to simply use template deduction, and cast the parameter to what you're wanting to use between the brackets. a[cast(int)0] (although zero is already an int);
Re: template operator overload
On Wednesday, 27 November 2013 at 17:25:49 UTC, Shammah Chancellor wrote: On 2013-11-27 16:07:50 +, Namespace said: Just out of curiosity: Is it possible to call an overloaded operator with a template type? import std.stdio; struct A { void opIndex(T)(size_t index) { } } void main() { A a; a.opIndex!int(0); // [1] a!int[0]; // [2] } [1] works, but [2] fails. How can I call opIndex with bracket syntax and a typename? Or is this not possible? You need to simply use template deduction, and cast the parameter to what you're wanting to use between the brackets. a[cast(int)0] (although zero is already an int); Inside the brackets I want an int. But I also want an extra type. E.g. A a; a!string[4];
Re: template operator overload
On Wednesday, 27 November 2013 at 17:47:13 UTC, bearophile wrote: Namespace: void main() { A a; a.opIndex!int(0); // [1] a!int[0]; // [2] } [1] works, but [2] fails. How can I call opIndex with bracket syntax and a typename? Or is this not possible? I think that's not supported by D syntax. So if you want that, you need to use a syntax like a.at!int(0). Bye, bearophile Too bad. Would have been really awesome.
Any trick for defining an operator overload in a different namespace?
I'm trying to achieve the syntax opts[...] = 123, rather than using the more direct this[...] = 123. I can use this code: - class C { this() { opts = Opts(this); opts[foo] = 1; } struct Opts { C c; void opIndexAssign(T)(T value, string option) { c.assign(option, value); } } Opts opts; private void assign(string option, int value) { } } void main() { auto c = new C(); } - But this explicitly stores the 'this' reference in the struct, I was wondering if anyone knows of a trick to avoid having to do that. As you can tell I just want a more convenient operator-based syntax over calling the 'assign' method, but I don't want the operator to live in the class space itself (because then I'd have to use this[...] = that, which is a little quirky for my taste).
Re: Any trick for defining an operator overload in a different namespace?
On 08/31/2013 03:07 AM, Andrej Mitrovic wrote: I'm trying to achieve the syntax opts[...] = 123, rather than using the more direct this[...] = 123. I can use this code: - class C { this() { opts = Opts(this); opts[foo] = 1; } struct Opts { C c; void opIndexAssign(T)(T value, string option) { c.assign(option, value); } } Opts opts; private void assign(string option, int value) { } } void main() { auto c = new C(); } - But this explicitly stores the 'this' reference in the struct, I was wondering if anyone knows of a trick to avoid having to do that. As you can tell I just want a more convenient operator-based syntax over calling the 'assign' method, but I don't want the operator to live in the class space itself (because then I'd have to use this[...] = that, which is a little quirky for my taste). This is the limitation of inner structs' not having an 'outer' reference, right? Even if that were automatically available, it would still need a reference similar to your explicit 'c' reference. I think... :) Ali
Re: Any trick for defining an operator overload in a different namespace?
On 9/1/13, Ali Çehreli acehr...@yahoo.com wrote: This is the limitation of inner structs' not having an 'outer' reference, right? Right, but this was just a workaround. Anyway I did just realize I can use opDispatch for this: - class C { this() { this.opts[foo] = 1; } private auto opDispatch(string field : opts)() { return this; } private void opIndexAssign(T)(T value, string option) { assign(option, value); } private void assign(string option, int value) { } } - It might seem a little funny that the only thing it does is just returns 'this', which we already had. But I wanted to avoid writing 'this[foo] = 1;'. Well at the end of the day this may or may not be what I wanted, since I still want to hide opDispatch. Oh well.. :)
static / global operator overload
I can't find anything so I ask here: what was the decision to disallow static or global operator overloads? In C++ you can declare operator overloads inside and outside of classes (the latter is more popular), so why wasn't this introduced in D also? Thanks in advance. :)
Re: static / global operator overload
On 08/18/2013 07:34 AM, Namespace wrote: In C++ you can declare operator overloads inside and outside of classes (the latter is more popular) The latter is popular because a global operator takes advantage of implicit type conversions. A global operator+ allows using an int even on the left-hand side of the operator. As a result, assuming that MyInt can be constructed from an int, when there is // Assume this is defined outside of MyInt definition MyInt operator+(MyInt lhs, MyInt rhs); the expression 1 + MyInt(2) is lowered to operator+(MyInt(1), MyInt(2)) so why wasn't this introduced in D also? My guess is that there is no implicit construction of objects in D anyway so there wouldn't be that benefit. Ali
Re: static / global operator overload
On Sunday, 18 August 2013 at 15:29:26 UTC, Ali Çehreli wrote: On 08/18/2013 07:34 AM, Namespace wrote: In C++ you can declare operator overloads inside and outside of classes (the latter is more popular) The latter is popular because a global operator takes advantage of implicit type conversions. A global operator+ allows using an int even on the left-hand side of the operator. As a result, assuming that MyInt can be constructed from an int, when there is // Assume this is defined outside of MyInt definition MyInt operator+(MyInt lhs, MyInt rhs); the expression 1 + MyInt(2) is lowered to operator+(MyInt(1), MyInt(2)) so why wasn't this introduced in D also? My guess is that there is no implicit construction of objects in D anyway so there wouldn't be that benefit. Ali D defines the member opBinaryRight, which makes global operators un-needed. // struct S { void opBinary(alias s)(int i) if (s == +) { writeln(s); } void opBinaryRight(alias s)(int i) if (s == +) { return this + i; } } void main() { S s; s + 5; 5 + s; } // Doing this also helps avoid poluting the global name-space with operators.
Re: static / global operator overload
On Sunday, 18 August 2013 at 15:29:26 UTC, Ali Çehreli wrote: On 08/18/2013 07:34 AM, Namespace wrote: In C++ you can declare operator overloads inside and outside of classes (the latter is more popular) The latter is popular because a global operator takes advantage of implicit type conversions. A global operator+ allows using an int even on the left-hand side of the operator. As a result, assuming that MyInt can be constructed from an int, when there is // Assume this is defined outside of MyInt definition MyInt operator+(MyInt lhs, MyInt rhs); the expression 1 + MyInt(2) is lowered to operator+(MyInt(1), MyInt(2)) so why wasn't this introduced in D also? My guess is that there is no implicit construction of objects in D anyway so there wouldn't be that benefit. Ali It's also preferred (at least by me) because such methods don't have to be in a class/struct and blows it up. They don't effect the class/struct and thanks to UFCS we still could call them like member methods. So IMO because they have no effect in a class/struct they shouldn't be there. Compare: bool opEquals(ref const A a) { ... } inside of struct A versus: bool opEquals(ref const A lhs, ref const A rhs) { ... } I would prefer the last one. But I would like to see an official thread for this, if any exist. Do you know one? I'm just startled that D follows this way. :)
Re: static / global operator overload
On Sunday, 18 August 2013 at 21:23:05 UTC, Namespace wrote: On Sunday, 18 August 2013 at 15:29:26 UTC, Ali Çehreli wrote: On 08/18/2013 07:34 AM, Namespace wrote: In C++ you can declare operator overloads inside and outside of classes (the latter is more popular) The latter is popular because a global operator takes advantage of implicit type conversions. A global operator+ allows using an int even on the left-hand side of the operator. As a result, assuming that MyInt can be constructed from an int, when there is // Assume this is defined outside of MyInt definition MyInt operator+(MyInt lhs, MyInt rhs); the expression 1 + MyInt(2) is lowered to operator+(MyInt(1), MyInt(2)) so why wasn't this introduced in D also? My guess is that there is no implicit construction of objects in D anyway so there wouldn't be that benefit. Ali It's also preferred (at least by me) because such methods don't have to be in a class/struct and blows it up. They don't effect the class/struct and thanks to UFCS we still could call them like member methods. So IMO because they have no effect in a class/struct they shouldn't be there. Compare: bool opEquals(ref const A a) { ... } inside of struct A versus: bool opEquals(ref const A lhs, ref const A rhs) { ... } I would prefer the last one. But I would like to see an official thread for this, if any exist. Do you know one? I'm just startled that D follows this way. :) The possibility of static operator was raised, specifically for opDollar, in std.range, for the possibility of it automatically resolving to length. Reception for *just* this was kind of cold. I remember it being downright hostile for UFCS operators in general. The full conversation is here: http://d.puremagic.com/issues/show_bug.cgi?id=7177 Note that while UFCS was discussed, it wasn't the root of the discussion :/
Re: parse json-string - operator overload error
On Wednesday, 1 December 2010 at 08:17:37 UTC, zusta wrote: Hey guys, I'm trying to read a JSON-formated file. The parsing of the file seems to be correct, but I always get the following error: Error: no [] operator overload for type JSONValue. For testing purposes, I also tried the code of http://www.digitalmars.com/d/archives/digitalmars/D/std.json_API_improvement_ -_Request_for_code_review_117261.html#N117302 without success (same error). My currently code looks like this: import std.stdio : writeln; import std.json; import std.stream; import std.conv; void main(string[] args) { File f = new File(test.json, FileMode.In); string content = to!(string)(f.readString(f.available())); JSONValue t = parseJSON(content); writeln(t[test]); f.close(); } I hope anyone can help to find out what's wrong with the code above. Assuming the file reading was not the fault: string content = { \test\: \1\ }; JSONValue[string] t = parseJSON(content).object; writeln(t[test].str); This is one way to access the data in the file.
primitive type operator overload
Hello, I want to overload a primitive type operator so that I can do something like double a; myStruct b; writeln(a + b); but have no idea how to do it. Something similar(?) is already implemented in the language, i.e. double x; double[] y; writeln(x + y); but after searching the dmd2/src, what I found didn't offer any help. -Dominic Jones
Re: primitive type operator overload
Dominic Jones: I want to overload a primitive type operator so that I can do something like double a; myStruct b; writeln(a + b); You can't overload the operator of a primitive, but binary operators come in left and right versions: http://dlang.org/operatoroverloading.html#Binary a.opBinary!(op)(b) b.opBinaryRight!(op)(a) so adding an inverse + operator inside myStruct is possible. Bye, bearophile
Re: primitive type operator overload
Am 20.04.2012 18:41, schrieb bearophile: Dominic Jones: I want to overload a primitive type operator so that I can do something like double a; myStruct b; writeln(a + b); You can't overload the operator of a primitive, but binary operators come in left and right versions: ... Bye, bearophile Shouldn't a consequence of UFCS be that you can overload binary operators for primitives, as should global overloads (like in C++).
Re: primitive type operator overload
On Fri, Apr 20, 2012 at 07:12:41PM +0200, Mafi wrote: Am 20.04.2012 18:41, schrieb bearophile: Dominic Jones: I want to overload a primitive type operator so that I can do something like double a; myStruct b; writeln(a + b); You can't overload the operator of a primitive, but binary operators come in left and right versions: ... Bye, bearophile Shouldn't a consequence of UFCS be that you can overload binary operators for primitives, as should global overloads (like in C++). UFCS only kicks in if no matching method is found for the given type. So UFCS can be used to provide default implementations for when an operator is not defined for a given type, but the operator defined by the type takes precedence over UFCS. T -- How are you doing? Doing what?
parse json-string - operator overload error
Hey guys, I'm trying to read a JSON-formated file. The parsing of the file seems to be correct, but I always get the following error: Error: no [] operator overload for type JSONValue. For testing purposes, I also tried the code of http://www.digitalmars.com/d/archives/digitalmars/D/std.json_API_improvement_ -_Request_for_code_review_117261.html#N117302 without success (same error). My currently code looks like this: import std.stdio : writeln; import std.json; import std.stream; import std.conv; void main(string[] args) { File f = new File(test.json, FileMode.In); string content = to!(string)(f.readString(f.available())); JSONValue t = parseJSON(content); writeln(t[test]); f.close(); } I hope anyone can help to find out what's wrong with the code above.