digitalmars.D.learn - logical operands on strings
- Erik van Velzen (24/24) Jan 12 2014 I would like to do this:
- Meta (4/28) Jan 12 2014 It looks like your opBinary on strings is an attempt at globally
- Erik van Velzen (6/10) Jan 12 2014 How would I do that without rewriting an entire string class? It
- TheFlyingFiddle (30/38) Jan 12 2014 Well something like this.
- Meta (5/46) Jan 12 2014 You can also use opBinaryRight for when your custom string class
- John Colvin (25/36) Jan 12 2014 global operator overloads aren't allowed in D. For your
- Mike Parker (2/9) Jan 12 2014 In D, string is not a class. It's an alias for an immutable array of cha...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (24/48) Jan 12 2014 XOR is not a valid operation on a UTF-8 code unit. ;) It makes more
- Meta (2/4) Jan 12 2014 Is this a bug or intended?
- John Colvin (4/9) Jan 12 2014 intended. It would require an implicit allocation, which is
I would like to do this: string one = x"315c4eeaa8b5f8aaf9174145bf43e1784b"; string two = x"c29398f5f3251a0d47e503c66e935de81230b59b7a"; string three = one ^ two; The closests I've been able to get is: string three = xor(one, two); string xor(string one, string two) { int len = min(one.length, two.length); string result; for(int i=0; i<len; i++) { result ~= one[i] ^ two[i]; } return cast(string)result; } Question 1: is there a more elegant way to implement the function xor? (foreach-ish or std.algorithm) Then I tried to add operator overloading: string opBinary(string op)(string lhs, string rhs) { static if( op == "^" ) return xor(lhs, rhs); else static assert(false, "operator not possible"); } But it doesn't invoke this function. Question 2: how would I implement "^" for strings?
Jan 12 2014
On Sunday, 12 January 2014 at 18:21:06 UTC, Erik van Velzen wrote:I would like to do this: string one = x"315c4eeaa8b5f8aaf9174145bf43e1784b"; string two = x"c29398f5f3251a0d47e503c66e935de81230b59b7a"; string three = one ^ two; The closests I've been able to get is: string three = xor(one, two); string xor(string one, string two) { int len = min(one.length, two.length); string result; for(int i=0; i<len; i++) { result ~= one[i] ^ two[i]; } return cast(string)result; } Question 1: is there a more elegant way to implement the function xor? (foreach-ish or std.algorithm) Then I tried to add operator overloading: string opBinary(string op)(string lhs, string rhs) { static if( op == "^" ) return xor(lhs, rhs); else static assert(false, "operator not possible"); } But it doesn't invoke this function. Question 2: how would I implement "^" for strings?It looks like your opBinary on strings is an attempt at globally overriding the XOR operator. I'm almost 100% sure this won't work in D. All operator overloads have to be part of a class or struct.
Jan 12 2014
On Sunday, 12 January 2014 at 18:28:38 UTC, Meta wrote:It looks like your opBinary on strings is an attempt at globally overriding the XOR operator. I'm almost 100% sure this won't work in D. All operator overloads have to be part of a class or struct.How would I do that without rewriting an entire string class? It seems I can't even inherit from string. Forgive me for making the comparison, but I believe in C++ i can simply implement this function and be done with it: string operator^(string lhs, string rhs);
Jan 12 2014
On Sunday, 12 January 2014 at 18:37:40 UTC, Erik van Velzen wrote:On Sunday, 12 January 2014 at 18:28:38 UTC, Meta wrote:Well something like this. struct MyString { string value; alias value this; auto opBinary(string op)(string rhs) if( op == "^" ) { string result; foreach(i; 0 .. min(value.length, rhs.length)) result ~= value[i] ^ rhs[i]; return MyString(result); } } auto mstr(string s) { return MyString(s); } auto s = "Hello"; auto s2 = "World"; auto res = s.mstr ^ s2; or string res = s.mstr ^ s2; //If you want the result to be a string. While this works it's not that much better then the simple: auto s = "Hello"; auto s2 = "World"; auto res = s.xor(s2);It looks like your opBinary on strings is an attempt at globally overriding the XOR operator. I'm almost 100% sure this won't work in D. All operator overloads have to be part of a class or struct.How would I do that without rewriting an entire string class?It seems I can't even inherit from string.In D a string is not a class its just an immutable array (slice) of char. alias string = immutable(char[]);
Jan 12 2014
On Sunday, 12 January 2014 at 19:12:13 UTC, TheFlyingFiddle wrote:On Sunday, 12 January 2014 at 18:37:40 UTC, Erik van Velzen wrote:You can also use opBinaryRight for when your custom string class is on the right side of the operand, so string ^ MyString also works. This pretty much obviates the need for global operator overloading, at least in this case.On Sunday, 12 January 2014 at 18:28:38 UTC, Meta wrote:Well something like this. struct MyString { string value; alias value this; auto opBinary(string op)(string rhs) if( op == "^" ) { string result; foreach(i; 0 .. min(value.length, rhs.length)) result ~= value[i] ^ rhs[i]; return MyString(result); } } auto mstr(string s) { return MyString(s); } auto s = "Hello"; auto s2 = "World"; auto res = s.mstr ^ s2; or string res = s.mstr ^ s2; //If you want the result to be a string. While this works it's not that much better then the simple: auto s = "Hello"; auto s2 = "World"; auto res = s.xor(s2);It looks like your opBinary on strings is an attempt at globally overriding the XOR operator. I'm almost 100% sure this won't work in D. All operator overloads have to be part of a class or struct.How would I do that without rewriting an entire string class?It seems I can't even inherit from string.In D a string is not a class its just an immutable array (slice) of char. alias string = immutable(char[]);
Jan 12 2014
On Sunday, 12 January 2014 at 18:37:40 UTC, Erik van Velzen wrote:On Sunday, 12 January 2014 at 18:28:38 UTC, Meta wrote:global operator overloads aren't allowed in D. For your particular problem I would construct a wrapper around string using psuedo-inheritance via 'alias this': struct MyString { string nativeStr; alias nativeStr this; auto opBinary(string op)(string rhs) if(op == "^") { return xor(nativeStr, rhs); } void opOpBinary(string op)(string rhs) if(op == "^") { nativeStr = xor(nativeStr, rhs); } } All normal string operations on a MyString will be applied to nativeStr thanks to alias this, except the ^ and ^= whch are intercepted by the opBinary and opOpBinary methods in MyString. The ^= could be more efficient by working in-place. Also, you should pre-allocate the return string in xor as it's a lot quicker than doing repeated append operations.It looks like your opBinary on strings is an attempt at globally overriding the XOR operator. I'm almost 100% sure this won't work in D. All operator overloads have to be part of a class or struct.How would I do that without rewriting an entire string class? It seems I can't even inherit from string. Forgive me for making the comparison, but I believe in C++ i can simply implement this function and be done with it: string operator^(string lhs, string rhs);
Jan 12 2014
On 1/13/2014 3:37 AM, Erik van Velzen wrote:On Sunday, 12 January 2014 at 18:28:38 UTC, Meta wrote:In D, string is not a class. It's an alias for an immutable array of char.It looks like your opBinary on strings is an attempt at globally overriding the XOR operator. I'm almost 100% sure this won't work in D. All operator overloads have to be part of a class or struct.How would I do that without rewriting an entire string class? It seems I can't even inherit from string.
Jan 12 2014
On 01/12/2014 10:21 AM, Erik van Velzen wrote:I would like to do this: string one = x"315c4eeaa8b5f8aaf9174145bf43e1784b"; string two = x"c29398f5f3251a0d47e503c66e935de81230b59b7a"; string three = one ^ two; The closests I've been able to get is: string three = xor(one, two); string xor(string one, string two) { int len = min(one.length, two.length); string result; for(int i=0; i<len; i++) { result ~= one[i] ^ two[i]; } return cast(string)result; } Question 1: is there a more elegant way to implement the function xor? (foreach-ish or std.algorithm) Then I tried to add operator overloading: string opBinary(string op)(string lhs, string rhs) { static if( op == "^" ) return xor(lhs, rhs); else static assert(false, "operator not possible"); } But it doesn't invoke this function. Question 2: how would I implement "^" for strings?XOR is not a valid operation on a UTF-8 code unit. ;) It makes more sense to work with ubyte arrays. However, I found two usability issues with it: 1) std.conv.to did not work from string to ubyte[]; so, I wrote a function. 2) Array-wise operations does not support the following syntax auto three = one[] ^ two[]; Otherwise, ^= works with slices: import std.stdio; ubyte[] toBytes(string s) { return cast(ubyte[])s.dup; } void main() { ubyte[] one = x"55".toBytes; ubyte[] two = x"aa".toBytes; ubyte[] three = one.dup; three[] ^= two[]; assert(one == x"55"); assert(two == x"aa"); assert(three == x"ff"); } Ali
Jan 12 2014
On Sunday, 12 January 2014 at 19:22:57 UTC, Ali Çehreli wrote:2) Array-wise operations does not support the following syntax auto three = one[] ^ two[];Is this a bug or intended?
Jan 12 2014
On Sunday, 12 January 2014 at 19:27:18 UTC, Meta wrote:On Sunday, 12 January 2014 at 19:22:57 UTC, Ali Çehreli wrote:intended. It would require an implicit allocation, which is incongruent with array operations being fast. It's been discussed at length.2) Array-wise operations does not support the following syntax auto three = one[] ^ two[];Is this a bug or intended?
Jan 12 2014