Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 12, 2014 logical operands on strings | ||||
---|---|---|---|---|
| ||||
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? |
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik van Velzen | 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.
|
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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);
|
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik van Velzen | 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: >> >> 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? 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 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[]); |
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik van Velzen | 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:
>>
>> 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);
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.
|
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik van Velzen | 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
|
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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?
|
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to TheFlyingFiddle | 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:
>> 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?
>
> 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 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[]);
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.
|
January 12, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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:
>> 2) Array-wise operations does not support the following syntax
>>
>> auto three = one[] ^ two[];
>
> Is this a bug or intended?
intended. It would require an implicit allocation, which is incongruent with array operations being fast. It's been discussed at length.
|
January 13, 2014 Re: logical operands on strings | ||||
---|---|---|---|---|
| ||||
Posted in reply to Erik van Velzen | On 1/13/2014 3:37 AM, Erik van Velzen wrote:
> 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.
In D, string is not a class. It's an alias for an immutable array of char.
|
Copyright © 1999-2021 by the D Language Foundation