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









"Meta" <jared771 gmail.com> 