digitalmars.D - InternetAddress comparison fail
- Jonathan Marler (12/12) Jan 02 2015 Why doesn't the equals operator work on the InternetAddress class?
- MattCoder (16/18) Jan 02 2015 It fails as the example below:
- MattCoder (13/15) Jan 02 2015 I forgot to paste an example:
- Jonathan Marler (15/34) Jan 03 2015 Thanks for the suggestion. However, it brings me a little pain
- MattCoder (32/39) Jan 03 2015 Hmm well, you don't need to convert anything (like ushort to
- Jonathan Marler (5/44) Jan 03 2015 My problem isn't comparing the two addresses..I can do that using
- MattCoder (5/7) Jan 03 2015 Yes I understood your problem and like I said on the previous
- David Eagen (6/19) Jan 02 2015 I ran into this too and made a helper to do the comparison (using
- Jon (5/27) Jan 02 2015 Still, shouldn't the == operator do a deep compare of the two
- Steven Schveighoffer (4/7) Jan 02 2015 InternetAddress is a class. Default comparison for class is identity
- Jon (11/19) Jan 02 2015 Thanks for clearing that up - it's been a while since I've played
- Steven Schveighoffer (11/29) Jan 02 2015 I can see how the wording is confusing, but that statement is somewhat
- Jonathan Marler (6/45) Jan 03 2015 So what is the right way to compare the contents of 2 classes? I
- Martin Nowak (4/8) Jan 03 2015 Sure, someone should make a pull and implement opEquals for the
- Martin Nowak (3/5) Jan 03 2015 In the meantime addr1.tupleof == addr2.tupleof is a useful workaround,
- Jonathan Marler (5/11) Jan 03 2015 Ah I hadn't thought of using tupleof, works nicely. It will
- Jonathan Marler (13/21) Jan 03 2015 I've made a pull request
- Tobias Pankrath (6/16) Jan 03 2015 Doesn't TDPL talk about that the correct behaviour is this one
- Martin Nowak (7/8) Jan 03 2015 This [1] is the implementation and it calls opEquals. If that's not
Why doesn't the equals operator work on the InternetAddress class? import std.stdio; import std.socket; void main() { auto addr1 = new InternetAddress("192.168.0.1", 80); auto addr2 = new InternetAddress("192.168.0.1", 80); assert(addr1 == addr2); // FAILS } If I am not mistaken, the == operator is overriden by the opEquals method. I don't see any opEquals method in std.socket so I'm wondering if this is by design or someone overlooked it?
Jan 02 2015
On Saturday, 3 January 2015 at 01:16:39 UTC, Jonathan Marler wrote:Why doesn't the equals operator work on the InternetAddress class?It fails as the example below: import std.stdio; class foo{} void main(){ auto a = new foo; auto b = new foo; assert(a == b); } I believe you need to compare the values inside those class right? Anyway, the way I'd do this is changing the line: assert(addr1 == addr2); // FAILS to assert(addr1.toAddrString() == addr2.toAddrString()); Matheus.
Jan 02 2015
On Saturday, 3 January 2015 at 01:59:40 UTC, MattCoder wrote:I believe you need to compare the values inside those class right?I forgot to paste an example: import std.stdio; class foo{ int i = 0; bool opEquals(foo obj){ return this.i == obj.i;} } void main(){ auto a = new foo; auto b = new foo; assert(a.opEquals(b)); } Matheus.
Jan 02 2015
On Saturday, 3 January 2015 at 01:59:40 UTC, MattCoder wrote:On Saturday, 3 January 2015 at 01:16:39 UTC, Jonathan Marler wrote:Thanks for the suggestion. However, it brings me a little pain to see people use the toAddrString for comparison. An InternetAddress consists of a uint address and a ushort port. The comparison should be 2 integer comparisons. Using toAddrString results in the following steps: 1. Allocate memory for the InternetAddress (GC memory by the way) 2. Convert the uint address to an IP Address string 3. Convert the ushort port to a string. 4. Do steps 1-3 to the second InternetAddress 5. Do a string comparision with the two InternetAddresses. This is so inefficient it hurts me. The steps should be: 1. Compare the uint and ushort members of InternetAddress. done. Anyway, your suggestion works...but I hope you can understand why it hurts me to see it...lolWhy doesn't the equals operator work on the InternetAddress class?It fails as the example below: import std.stdio; class foo{} void main(){ auto a = new foo; auto b = new foo; assert(a == b); } I believe you need to compare the values inside those class right? Anyway, the way I'd do this is changing the line: assert(addr1 == addr2); // FAILS to assert(addr1.toAddrString() == addr2.toAddrString()); Matheus.
Jan 03 2015
On Saturday, 3 January 2015 at 16:39:05 UTC, Jonathan Marler wrote:Using toAddrString results in the following steps:1. Allocate memory for the InternetAddress (GC memory by the way) 2. Convert the uint address to an IP Address string 3. Convert the ushort port to a string. 4. Do steps 1-3 to the second InternetAddress 5. Do a string comparision with the two InternetAddresses.Hmm well, you don't need to convert anything (like ushort to string etc), you can compare the fields between these 2 classes directly: import std.stdio; import std.socket; class myIA : InternetAddress{ this(in char[] addr, ushort port){ super(addr, port); } bool opEquals(myIA obj){ foreach (i, v; this.tupleof) { if(v != obj.tupleof[i]){ return false; } } return true; } } void main(){ auto addr1 = new myIA("192.168.0.1", 80); auto addr2 = new myIA("192.168.0.1", 80); assert(addr1.opEquals(addr2)); } Overall I understood your point/pain, but unfortunately this is what I could do to manage your problem (I'm using D heavily for a couple months now). I'll continue looking over this thread to see what the experts will say. :) Matheus.
Jan 03 2015
On Saturday, 3 January 2015 at 17:26:29 UTC, MattCoder wrote:On Saturday, 3 January 2015 at 16:39:05 UTC, Jonathan Marler wrote:My problem isn't comparing the two addresses..I can do that using (addr1.addr == addr2.addr && addr1.port == addr2.port) my question was, should the InterenetAddress class have an opEquals or an opCmp or were they ommitted on purpose?Using toAddrString results in the following steps:1. Allocate memory for the InternetAddress (GC memory by the way) 2. Convert the uint address to an IP Address string 3. Convert the ushort port to a string. 4. Do steps 1-3 to the second InternetAddress 5. Do a string comparision with the two InternetAddresses.Hmm well, you don't need to convert anything (like ushort to string etc), you can compare the fields between these 2 classes directly: import std.stdio; import std.socket; class myIA : InternetAddress{ this(in char[] addr, ushort port){ super(addr, port); } bool opEquals(myIA obj){ foreach (i, v; this.tupleof) { if(v != obj.tupleof[i]){ return false; } } return true; } } void main(){ auto addr1 = new myIA("192.168.0.1", 80); auto addr2 = new myIA("192.168.0.1", 80); assert(addr1.opEquals(addr2)); } Overall I understood your point/pain, but unfortunately this is what I could do to manage your problem (I'm using D heavily for a couple months now). I'll continue looking over this thread to see what the experts will say. :) Matheus.
Jan 03 2015
On Saturday, 3 January 2015 at 17:37:19 UTC, Jonathan Marler wrote:my question was, should the InterenetAddress class have an opEquals or an opCmp or were they ommitted on purpose?Yes I understood your problem and like I said on the previous post I'm interested on the answer from the experts too. :) Matheus.
Jan 03 2015
On Saturday, 3 January 2015 at 01:16:39 UTC, Jonathan Marler wrote:Why doesn't the equals operator work on the InternetAddress class? import std.stdio; import std.socket; void main() { auto addr1 = new InternetAddress("192.168.0.1", 80); auto addr2 = new InternetAddress("192.168.0.1", 80); assert(addr1 == addr2); // FAILS } If I am not mistaken, the == operator is overriden by the opEquals method. I don't see any opEquals method in std.socket so I'm wondering if this is by design or someone overlooked it?I ran into this too and made a helper to do the comparison (using toAddrString) so I could move forward with my project. Adding opEquals and opCmp is probably low-hanging fruit and a good place for someone to start working on Phobos.
Jan 02 2015
On Saturday, 3 January 2015 at 03:11:05 UTC, David Eagen wrote:On Saturday, 3 January 2015 at 01:16:39 UTC, Jonathan Marler wrote:Still, shouldn't the == operator do a deep compare of the two InternetAddress objects in the absence of a defined opEquals method? I don't see why it should fail in the above example. -JonWhy doesn't the equals operator work on the InternetAddress class? import std.stdio; import std.socket; void main() { auto addr1 = new InternetAddress("192.168.0.1", 80); auto addr2 = new InternetAddress("192.168.0.1", 80); assert(addr1 == addr2); // FAILS } If I am not mistaken, the == operator is overriden by the opEquals method. I don't see any opEquals method in std.socket so I'm wondering if this is by design or someone overlooked it?I ran into this too and made a helper to do the comparison (using toAddrString) so I could move forward with my project. Adding opEquals and opCmp is probably low-hanging fruit and a good place for someone to start working on Phobos.
Jan 02 2015
On 1/3/15 12:32 AM, Jon wrote:Still, shouldn't the == operator do a deep compare of the two InternetAddress objects in the absence of a defined opEquals method? I don't see why it should fail in the above example.InternetAddress is a class. Default comparison for class is identity (refer to the same object). -Steve
Jan 02 2015
On Saturday, 3 January 2015 at 05:40:33 UTC, Steven Schveighoffer wrote:On 1/3/15 12:32 AM, Jon wrote:Thanks for clearing that up - it's been a while since I've played with D. Maybe back in D1 it did a deep compare? The docs still refer to == as doing a comparison of the object's contents though, unless I'm misreading it. Under http://dlang.org/expression: "For class objects, the == and != operators compare the contents of the objects." Maybe this needs to be updated. Thanks, -JonStill, shouldn't the == operator do a deep compare of the two InternetAddress objects in the absence of a defined opEquals method? I don't see why it should fail in the above example.InternetAddress is a class. Default comparison for class is identity (refer to the same object). -Steve
Jan 02 2015
On 1/3/15 12:51 AM, Jon wrote:On Saturday, 3 January 2015 at 05:40:33 UTC, Steven Schveighoffer wrote:I can see how the wording is confusing, but that statement is somewhat out of context. What it really means is that == and != *should* be comparing the contents. It is an explanatory statement as to why you cannot call obj == null; Because this translates to obj.opEquals(null), if obj is null, then it crashes (well, at least it used to). The true definition of the default is here: https://github.com/schveiguy/druntime/blob/master/src/object_.d#L107 -SteveOn 1/3/15 12:32 AM, Jon wrote:Thanks for clearing that up - it's been a while since I've played with D. Maybe back in D1 it did a deep compare? The docs still refer to == as doing a comparison of the object's contents though, unless I'm misreading it. Under http://dlang.org/expression: "For class objects, the == and != operators compare the contents of the objects." Maybe this needs to be updated.Still, shouldn't the == operator do a deep compare of the two InternetAddress objects in the absence of a defined opEquals method? I don't see why it should fail in the above example.InternetAddress is a class. Default comparison for class is identity (refer to the same object). -Steve
Jan 02 2015
On Saturday, 3 January 2015 at 06:01:24 UTC, Steven Schveighoffer wrote:On 1/3/15 12:51 AM, Jon wrote:So what is the right way to compare the contents of 2 classes? I thought it was to implement an opEquals method. It pains me to see people using the toAddrString function to compare Address classes:( This is so inefficient and unnecessary.On Saturday, 3 January 2015 at 05:40:33 UTC, Steven Schveighoffer wrote:I can see how the wording is confusing, but that statement is somewhat out of context. What it really means is that == and != *should* be comparing the contents. It is an explanatory statement as to why you cannot call obj == null; Because this translates to obj.opEquals(null), if obj is null, then it crashes (well, at least it used to). The true definition of the default is here: https://github.com/schveiguy/druntime/blob/master/src/object_.d#L107 -SteveOn 1/3/15 12:32 AM, Jon wrote:Thanks for clearing that up - it's been a while since I've played with D. Maybe back in D1 it did a deep compare? The docs still refer to == as doing a comparison of the object's contents though, unless I'm misreading it. Under http://dlang.org/expression: "For class objects, the == and != operators compare the contents of the objects." Maybe this needs to be updated.Still, shouldn't the == operator do a deep compare of the two InternetAddress objects in the absence of a defined opEquals method? I don't see why it should fail in the above example.InternetAddress is a class. Default comparison for class is identity (refer to the same object). -Steve
Jan 03 2015
On Saturday, 3 January 2015 at 16:33:56 UTC, Jonathan Marler wrote:So what is the right way to compare the contents of 2 classes? I thought it was to implement an opEquals method. It pains me to see people using the toAddrString function to compare Address classes:( This is so inefficient and unnecessary.Sure, someone should make a pull and implement opEquals for the Address classes, maybe also opHash.
Jan 03 2015
On 01/04/2015 12:45 AM, Martin Nowak wrote:Sure, someone should make a pull and implement opEquals for the Address classes, maybe also opHash.In the meantime addr1.tupleof == addr2.tupleof is a useful workaround, but it can't handle polymorphism.
Jan 03 2015
On Sunday, 4 January 2015 at 00:13:21 UTC, Martin Nowak wrote:On 01/04/2015 12:45 AM, Martin Nowak wrote:Ah I hadn't thought of using tupleof, works nicely. It will compare the entire address struct (sockaddr_in) which is a few extra comparisons then what is needed but that is pretty close. I'll try to think of tupleof more often in the future. Thanks.Sure, someone should make a pull and implement opEquals for the Address classes, maybe also opHash.In the meantime addr1.tupleof == addr2.tupleof is a useful workaround, but it can't handle polymorphism.
Jan 03 2015
On Saturday, 3 January 2015 at 23:46:01 UTC, Martin Nowak wrote:On Saturday, 3 January 2015 at 16:33:56 UTC, Jonathan Marler wrote:I've made a pull request (https://github.com/D-Programming-Language/phobos/pull/2839#di cussion_r22435562). I haven't used opEquals that much in D so I'm not super familiar with it. It does concern me a little though. I'm wondering why the type specific opEquals isn't called first before the generic opEquals(Object) method when using the '==' operator. According to the documentation, (a == b), where a and b are classes, is rewritten as ".object.opEquals(a, b)". I'm just wondering why there has to be overhead when using the '==' operator. Instead, the type specific opEquals operator should be called, then if it does not exist, then the generic ".object.opEquals" method should be used. Why isn't it done this way?So what is the right way to compare the contents of 2 classes? I thought it was to implement an opEquals method. It pains me to see people using the toAddrString function to compare Address classes:( This is so inefficient and unnecessary.Sure, someone should make a pull and implement opEquals for the Address classes, maybe also opHash.
Jan 03 2015
I can see how the wording is confusing, but that statement is somewhat out of context. What it really means is that == and != *should* be comparing the contents. It is an explanatory statement as to why you cannot call obj == null; Because this translates to obj.opEquals(null), if obj is null, then it crashes (well, at least it used to). The true definition of the default is here: https://github.com/schveiguy/druntime/blob/master/src/object_.d#L107 -SteveDoesn't TDPL talk about that the correct behaviour is this one https://github.com/schveiguy/druntime/blob/master/src/object_.d#L162 and a == b should be rewritten to opEquals(a, b) which will fallback to identity if a user defined class has no opEquals defined? Could anyone clarify what the actual and intended behaviour is?
Jan 03 2015
On 01/03/2015 05:42 PM, Tobias Pankrath wrote:Could anyone clarify what the actual and intended behaviour is?This [1] is the implementation and it calls opEquals. If that's not overriden, the default [2] will use identity comparison. [1]: https://github.com/D-Programming-Language/druntime/blob/b3a8032e3960480a1588b3d1a4491808b4502d67/src/object_.d#L162 [2]: https://github.com/D-Programming-Language/druntime/blob/b3a8032e3960480a1588b3d1a4491808b4502d67/src/object_.d#L109
Jan 03 2015