logical operands on strings

2014-01-12 Thread Erik van Velzen

I would like to do this:

string one = x315c4eeaa8b5f8aaf9174145bf43e1784b;
string two = xc29398f5f3251a0d47e503c66e935de81230b59b7a;
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; ilen; 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?


Re: logical operands on strings

2014-01-12 Thread Meta

On Sunday, 12 January 2014 at 18:21:06 UTC, Erik van Velzen wrote:

I would like to do this:

string one = x315c4eeaa8b5f8aaf9174145bf43e1784b;
string two = xc29398f5f3251a0d47e503c66e935de81230b59b7a;
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; ilen; 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.


Re: logical operands on strings

2014-01-12 Thread Erik van Velzen

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);


Re: logical operands on strings

2014-01-12 Thread TheFlyingFiddle

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[]);



Re: logical operands on strings

2014-01-12 Thread John Colvin

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.


Re: logical operands on strings

2014-01-12 Thread Ali Çehreli

On 01/12/2014 10:21 AM, Erik van Velzen wrote:

I would like to do this:

 string one = x315c4eeaa8b5f8aaf9174145bf43e1784b;
 string two = xc29398f5f3251a0d47e503c66e935de81230b59b7a;
 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; ilen; 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 = x55.toBytes;
ubyte[] two = xaa.toBytes;

ubyte[] three = one.dup;
three[] ^= two[];

assert(one == x55);
assert(two == xaa);
assert(three == xff);
}

Ali



Re: logical operands on strings

2014-01-12 Thread Meta

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.


Re: logical operands on strings

2014-01-12 Thread Meta

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?


Re: logical operands on strings

2014-01-12 Thread John Colvin

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.


Re: logical operands on strings

2014-01-12 Thread Mike Parker

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.