Nice example for operator overload resulting in readable linear algebra expressions

2021-11-19 Thread Martin Tschierschke via Digitalmars-d-learn

I just want to share a view lines of code.
The availability of operator overloading can result in very short 
and precise code for linear algebra.
To test/explore it a little I just modified the alias this 
example:

```
#!/usr/bin/env rdmd
struct Point
{
double[2] p;
// Forward all undefined symbols to p
alias p this;
auto opBinary(string op)(Point rhs)
{
static if (op == "+")
{
Point ret;
ret[0] = p[0] + rhs.p[0];
ret[1] = p[1] + rhs.p[1];
return ret;
}
else static if (op == "-")
{
Point ret;
ret[0] = p[0] - rhs.p[0];
ret[1] = p[1] - rhs.p[1];
return ret;
}
else static if (op == "*")
return p[0] * rhs.p[0] + p[1] * rhs.p[1];
else
static assert(0, "Operator " ~ op ~ " not 
implemented");

}
}

void main()
{
import std.stdio;// : writefln,write;

// Point behaves like a `double[2]` ...
Point p1, p2;
p1 = [2, 1], p2 = [1, 1];
// ... but with extended functionality
writef("p1*(p1 + p2) = %s*(%s + %s) =", p1, p1, p2);
write(p1 * (p1 + p2)); // compare this to code without 
operator overload:

}
```

Compare: ``p1 * (p1 + p2)`` to something with a structure like 
``dot(p1,(add(p1,p2)).``

(With the Dlangs UFCS it might become: ``p1.dot(p1.add(p2))`` )





Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)

2020-12-07 Thread Paul Backus via Digitalmars-d-learn

On Monday, 7 December 2020 at 06:18:33 UTC, mw wrote:

Now, how to convert it to a native array:

  double[] row = record;

Error: cannot implicitly convert expression record of type 
Tuple!(double, double, double, ..., double) to double[]


(I know for tuple, we can do: double[] arr = [record];)


double[] row = [record.expand];


Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)

2020-12-06 Thread mw via Digitalmars-d-learn

On Monday, 7 December 2020 at 04:38:07 UTC, Paul Backus wrote:

On Monday, 7 December 2020 at 04:03:05 UTC, mw wrote:
So my next question: given N, how do I create a Tuple!(double, 
double, ... n-double) type programmatically?


import std.meta: Repeat;

alias NDoubles = Tuple!(Repeat!(N, double));

Note that N must be a compile-time constant, since the number 
of elements in a Tuple is fixed at compile time.


Yes, I just realized that Tuple (upper T, compile time) and tuple 
(lower t) are different things.


Now, how to convert it to a native array:

  double[] row = record;

Error: cannot implicitly convert expression record of type 
Tuple!(double, double, double, ..., double) to double[]


(I know for tuple, we can do: double[] arr = [record];)


Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)

2020-12-06 Thread Paul Backus via Digitalmars-d-learn

On Monday, 7 December 2020 at 04:03:05 UTC, mw wrote:
So my next question: given N, how do I create a Tuple!(double, 
double, ... n-double) type programmatically?


import std.meta: Repeat;

alias NDoubles = Tuple!(Repeat!(N, double));

Note that N must be a compile-time constant, since the number of 
elements in a Tuple is fixed at compile time.


Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)

2020-12-06 Thread mw via Digitalmars-d-learn

On Monday, 7 December 2020 at 03:51:02 UTC, Paul Backus wrote:

On Monday, 7 December 2020 at 02:25:23 UTC, mw wrote:
onlineapp.d(8): Error: no [] operator overload for type 
CsvRecord!(int, cast(Malformed)1, string, dchar)


should `r`'s type be integer array? and how do I access each 
elelment of the row?


Thanks.


The docs [1] say that csvReader returns an input range, not an 
array. Input ranges don't support indexing, only iteration 
(e.g. with `foreach`). If you want an array, you will have to 
use `std.array.array` to create one.


[1] http://phobos.dpldocs.info/std.csv.csvReader.1.html


Thanks.

I saw the 1st example on this page:

https://dlang.org/phobos/std_csv.html

foreach (record; csvReader!(Tuple!(string, string, int))(text))
{
writefln("%s works as a %s and earns $%d per year",
 record[0], record[1], record[2]);
}

So my next question: given N, how do I create a Tuple!(double, 
double, ... n-double) type programmatically?







Re: how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)

2020-12-06 Thread Paul Backus via Digitalmars-d-learn

On Monday, 7 December 2020 at 02:25:23 UTC, mw wrote:
onlineapp.d(8): Error: no [] operator overload for type 
CsvRecord!(int, cast(Malformed)1, string, dchar)


should `r`'s type be integer array? and how do I access each 
elelment of the row?


Thanks.


The docs [1] say that csvReader returns an input range, not an 
array. Input ranges don't support indexing, only iteration (e.g. 
with `foreach`). If you want an array, you will have to use 
`std.array.array` to create one.


[1] http://phobos.dpldocs.info/std.csv.csvReader.1.html


how to access record[0] of a csv row? Error: no [] operator overload for type CsvRecord!(int, cast(Malformed)1, string, dchar)

2020-12-06 Thread mw via Digitalmars-d-learn

Hi,

I'm trying this code: i.e. print out the 1st element of each row

https://run.dlang.io/is/pG921a

void main()
{
import std.csv;
import std.stdio: write, writeln, writef, writefln;
import std.algorithm.comparison : equal;
string text = "76,26,22";
auto records = text.csvReader!int;
foreach(r; records) {writeln(r[0]);}   // line 8
assert(records.equal!equal([
[76, 26, 22],
]));
}


but I got a compile error:

onlineapp.d(8): Error: no [] operator overload for type 
CsvRecord!(int, cast(Malformed)1, string, dchar)


should `r`'s type be integer array? and how do I access each 
elelment of the row?


Thanks.



Re: operator overload for sh-like scripting ?

2020-02-17 Thread Simen Kjærås via Digitalmars-d-learn

On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote:

eg

   Sh(echo) < "meh";

struct Sh
{
 // you see the idea we have op overload for < here
}


You can't overload < separately - all the comparison operators 
(<, <=, >, >=) are handled via opCmp. Even if you choose to go 
down that route, there are other issues - opCmp needs to return 
something that may be compared to 0, since (a < b) is rewritten 
as (a.opCmp(b) < 0), and the compiler checks if you are simply 
discarding the return value of a comparison, so all in all, you 
shouldn't do that in D (and the hoops you have to jump through to 
make it work makes the code a lot less readable):


struct Sh {
int opCmp(string s) {
import std.stdio : writeln;
writeln(s);
return 0;
}
}

unittest {
Sh sh;
auto _ = sh < "baz";
}

This is also not chainable, so something like (sh < "foo" < 
"bar") won't work, even with parentheses.


There's also the issue of (a < b) having a defined meaning in D 
(a less than b), and such overloading leads to code that may be 
less readable. This is a point with differing opinions, and I'm 
not firmly on either side of that argument, but it's worth 
pointing out.


Now, if you absolutely want something that's somewhat similar in 
regular D code, there's <<:


struct Sh {
Sh opBinary(string op : "<<")(string s) {
import std.stdio : writeln;
writeln(s);
return this;
}
}

unittest {
Sh sh;
sh << "foo" << "bar";
}

While this works, it's a design choice that C++ has gotten a lot 
of flak for, including one of my favorite C++ quotes: "I saw 
'cout' being shifted 'Hello world' times to the left and stopped 
right there." There are cases where it's not at obvious to the 
reader of the code what's happening, so such operator overloading 
should be used with caution.


A better choice, perhaps, if using < is important, would be to 
use a DSL and have it obvious in the code that normal D rules 
aren't at play:


void fun() {
Sh sh;
mixin dsl!`
sh < "foo";
`;
}

At this point though, you're looking at a considerable chunk of 
code just for a bit of syntactic sugar.


--
  Simen


Re: operator overload for sh-like scripting ?

2020-02-17 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote:

   Sh(echo) < "meh";


Not allowed in D - it only does a comparison overload which 
covers < and > (and <= and >=).


Though we could do strings and stuff. especially with my string 
interpolation dip 
https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f we could make it work quite well!


operator overload for sh-like scripting ?

2020-02-17 Thread Basile B. via Digitalmars-d-learn

eg

   Sh(echo) < "meh";

struct Sh
{
 // you see the idea we have op overload for < here
}


Re: no [] operator overload for type Chunks!(char[])

2018-05-31 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/30/18 5:41 PM, Malte wrote:

On Wednesday, 30 May 2018 at 21:27:44 UTC, Ali Çehreli wrote:

On 05/30/2018 02:19 PM, Malte wrote:
Why does this code complain at the last line about a missing [] 
operator overload?


auto buffer = new char[6];
auto chunked = buffer.chunks(3);
chunked[1][2] = '!';

Same happens with wchar.
Dchar and byte work as expected.


UTF-8 auto decoding strikes again. :)

Even though the original container is char[], passing it through 
Phobos algorithms generated range of dchar. The thing is, those dchar 
elements are generated (decoded from chars) "on the fly" as one 
iterates over the range. Which means, there is no array of dchar to 
speak of, so there is no random access.




I see. Not what I would have expected, but makes sense for people 
working with UTF-8 strings.


Thanks for the fast answer.


You can use byCodeUnit to turn it back into an indexable range:

auto chunked = buffer.byCodeUnit.chunks(3);

-Steve


Re: no [] operator overload for type Chunks!(char[])

2018-05-30 Thread Malte via Digitalmars-d-learn

On Wednesday, 30 May 2018 at 21:27:44 UTC, Ali Çehreli wrote:

On 05/30/2018 02:19 PM, Malte wrote:
Why does this code complain at the last line about a missing 
[] operator overload?


auto buffer = new char[6];
auto chunked = buffer.chunks(3);
chunked[1][2] = '!';

Same happens with wchar.
Dchar and byte work as expected.


UTF-8 auto decoding strikes again. :)

Even though the original container is char[], passing it 
through Phobos algorithms generated range of dchar. The thing 
is, those dchar elements are generated (decoded from chars) "on 
the fly" as one iterates over the range. Which means, there is 
no array of dchar to speak of, so there is no random access.


Ali


I see. Not what I would have expected, but makes sense for people 
working with UTF-8 strings.


Thanks for the fast answer.


Re: no [] operator overload for type Chunks!(char[])

2018-05-30 Thread Ali Çehreli via Digitalmars-d-learn

On 05/30/2018 02:19 PM, Malte wrote:
Why does this code complain at the last line about a missing [] operator 
overload?


auto buffer = new char[6];
auto chunked = buffer.chunks(3);
chunked[1][2] = '!';

Same happens with wchar.
Dchar and byte work as expected.


UTF-8 auto decoding strikes again. :)

Even though the original container is char[], passing it through Phobos 
algorithms generated range of dchar. The thing is, those dchar elements 
are generated (decoded from chars) "on the fly" as one iterates over the 
range. Which means, there is no array of dchar to speak of, so there is 
no random access.


Ali


no [] operator overload for type Chunks!(char[])

2018-05-30 Thread Malte via Digitalmars-d-learn
Why does this code complain at the last line about a missing [] 
operator overload?


auto buffer = new char[6];
auto chunked = buffer.chunks(3);
chunked[1][2] = '!';

Same happens with wchar.
Dchar and byte work as expected.


Re: operator overload

2017-12-12 Thread dark777 via Digitalmars-d-learn

On Tuesday, 12 December 2017 at 17:13:55 UTC, Biotronic wrote:

On Tuesday, 12 December 2017 at 16:54:17 UTC, Biotronic wrote:
There is no way in C++ to set the format the way you want it. 
If you want binary output, you need to call a function like 
your binario function.


Of course this is not entirely true - there is a way, but it's 
ugly and probably not what you want:


struct BinStream
{
std::ostream& os;
BinStream(std::ostream& os) : os(os) {}

template
BinStream& operator<<(T&& value)
{
os << value;
return *this;
}

BinStream& operator<<(int value)
{
os << binario(value);
return *this;
}

std::ostream& operator<<(std::ios_base& (__cdecl 
*_Pfn)(std::ios_base&))

{
return os << _Pfn;
}
};

struct Bin
{
friend BinStream operator<<(std::ostream& os, const 
Bin& f);

} bin;

BinStream operator<<(std::ostream& os, const Bin& f)
{
return BinStream(os);
}

int main()
{
std::cout << "\n\t127 em binario: " << binario(127)
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em octal:   " << std::oct << 127
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em hexadecimal: " << std::hex << 127
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em decimal: " << std::dec << 127
<< "\n\t127 em binario: " << bin << 127 << "\n\n";
}

What is this black magic? Instead of overriding how 
std::ostream does formatting, Bin::Operator<< now returns a 
wrapper around a std::ostream, which special cases ints. If it 
gets any other format specifiers, it returns the ostream again, 
and the binary formatting is gone.


All in all, I think the conclusion is: Stay with D.

--
  Biotronic


I tried to execute with this part of the code

  std::ostream& operator<<(std::ios_base& (__cdecl 
*_Pfn)(std::ios_base&))

  {
   return os <<_Pfn;
  }

and it returns me this error below what is the include?

bin2.cxx:44:43: error: expected ‘,’ or ‘...’ before ‘(’ token
   std::ostream& operator<<(std::ios_base& (__cdecl 
*_Pfn)(std::ios_base&))

   ^
bin2.cxx: In member function ‘std::ostream& 
BinStream::operator<<(std::ios_base&)’:

bin2.cxx:46:16: error: ‘_Pfn’ was not declared in this scope
return os <<_Pfn;


Re: operator overload

2017-12-12 Thread dark777 via Digitalmars-d-learn

On Tuesday, 12 December 2017 at 17:13:55 UTC, Biotronic wrote:

On Tuesday, 12 December 2017 at 16:54:17 UTC, Biotronic wrote:
There is no way in C++ to set the format the way you want it. 
If you want binary output, you need to call a function like 
your binario function.


Of course this is not entirely true - there is a way, but it's 
ugly and probably not what you want:


struct BinStream
{
std::ostream& os;
BinStream(std::ostream& os) : os(os) {}

template
BinStream& operator<<(T&& value)
{
os << value;
return *this;
}

BinStream& operator<<(int value)
{
os << binario(value);
return *this;
}

std::ostream& operator<<(std::ios_base& (__cdecl 
*_Pfn)(std::ios_base&))

{
return os << _Pfn;
}
};

struct Bin
{
friend BinStream operator<<(std::ostream& os, const 
Bin& f);

} bin;

BinStream operator<<(std::ostream& os, const Bin& f)
{
return BinStream(os);
}

int main()
{
std::cout << "\n\t127 em binario: " << binario(127)
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em octal:   " << std::oct << 127
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em hexadecimal: " << std::hex << 127
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em decimal: " << std::dec << 127
<< "\n\t127 em binario: " << bin << 127 << "\n\n";
}

What is this black magic? Instead of overriding how 
std::ostream does formatting, Bin::Operator<< now returns a 
wrapper around a std::ostream, which special cases ints. If it 
gets any other format specifiers, it returns the ostream again, 
and the binary formatting is gone.


All in all, I think the conclusion is: Stay with D.

--
  Biotronic


I understand is basically this now I will see the necessity of 
this basically the example I wanted to do is to understand how it 
would be done in the most correct way, now I will study to do 
other cases if nescessarios but primarily is to convert only 
integers but you did exactly the that I wanted


I did some studies in the D language and it already has a way to 
convert to binary without any work just using% b as in printf you 
use% X or% x to convert to exa ... and that was the reason that 
made me interested in understand this was looking at some older 
glibc and the way printf understands these very interesting 
conversion operators


Re: operator overload

2017-12-12 Thread Biotronic via Digitalmars-d-learn

On Tuesday, 12 December 2017 at 16:54:17 UTC, Biotronic wrote:
There is no way in C++ to set the format the way you want it. 
If you want binary output, you need to call a function like 
your binario function.


Of course this is not entirely true - there is a way, but it's 
ugly and probably not what you want:


struct BinStream
{
std::ostream& os;
BinStream(std::ostream& os) : os(os) {}

template
BinStream& operator<<(T&& value)
{
os << value;
return *this;
}

BinStream& operator<<(int value)
{
os << binario(value);
return *this;
}

std::ostream& operator<<(std::ios_base& (__cdecl 
*_Pfn)(std::ios_base&))

{
return os << _Pfn;
}
};

struct Bin
{
friend BinStream operator<<(std::ostream& os, const Bin& 
f);

} bin;

BinStream operator<<(std::ostream& os, const Bin& f)
{
return BinStream(os);
}

int main()
{
std::cout << "\n\t127 em binario: " << binario(127)
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em octal:   " << std::oct << 127
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em hexadecimal: " << std::hex << 127
<< "\n\t127 em binario: " << bin << 127
<< "\n\t127 em decimal: " << std::dec << 127
<< "\n\t127 em binario: " << bin << 127 << "\n\n";
}

What is this black magic? Instead of overriding how std::ostream 
does formatting, Bin::Operator<< now returns a wrapper around a 
std::ostream, which special cases ints. If it gets any other 
format specifiers, it returns the ostream again, and the binary 
formatting is gone.


All in all, I think the conclusion is: Stay with D.

--
  Biotronic


Re: operator overload

2017-12-12 Thread Biotronic via Digitalmars-d-learn

On Tuesday, 12 December 2017 at 15:52:09 UTC, dark777 wrote:
I know that this community is not of c ++, but some time I have 
been studying how to do overload of ostream operators in c ++ 
and I even managed to get to this result but the same is not 
converting to binary only presents zeros as output to any 
number already tried to pass parameter of variable and yet he 
is not getting the number for conversion how to solve it so 
that it works correctly?


PS: if I use the same conversion algorithm in a function it 
converts normally it is not only converting to the output of 
the operator ..



https://pastebin.com/BXGXiiRk


This line:
<< "\n\t127 em binario: " << bin << 127 << "\n\n";

Your hope is that the '<< bin' part should behave just like 
std::hex does, except binary instead of hex. Right?


I'm afraid that's not how C++ formatting works. You can see a 
hint of what happens in the output you get:

127 em binario: 127

The zeroes are from the uninitialized int in your Bin struct, and 
the '127' is from the 127 you pass right after passing bin.


Translating to code that does not use operators, the behavior you 
expect is something like this:


std::cout.print("\n\t127 em binario: ");
std::cout.setFormat(bin);
std::cout.print(127); // Should use bin for formatting
std::cout.print("\n\n");

The actual behavior is something like this:

std ::cout.print("\n\t127 em binario: ");
std::cout.print(bin); // Prints the value stored in bin. That 
is, 0.
std::cout.print(127); // Prints 127 just the way it would 
otherwise print it.

std::cout.print("\n\n");

There is no way in C++ to set the format the way you want it. If 
you want binary output, you need to call a function like your 
binario function.


The point of overloading operator<<(std::ostream&, MyType) is not 
to format another type, but to be able to print MyType in a given 
way. Basically like toString() in D, C# or Java.


--
   Biotronic


operator overload

2017-12-12 Thread dark777 via Digitalmars-d-learn
I know that this community is not of c ++, but some time I have 
been studying how to do overload of ostream operators in c ++ and 
I even managed to get to this result but the same is not 
converting to binary only presents zeros as output to any number 
already tried to pass parameter of variable and yet he is not 
getting the number for conversion how to solve it so that it 
works correctly?


PS: if I use the same conversion algorithm in a function it 
converts normally it is not only converting to the output of the 
operator ..



https://pastebin.com/BXGXiiRk


Re: operator overload for enum

2016-06-10 Thread Timon Gehr via Digitalmars-d-learn

On 10.06.2016 13:02, Satoshi wrote:

Hello,
why operator overloading is not working as a static methods through the
UFCS?
...


It's an arbitrary limitation.
https://issues.dlang.org/show_bug.cgi?id=8062

(The specification has been updated in the meantime, it now documents 
the limitation explicitly. https://dlang.org/spec/operatoroverloading.html)



I need overload a << operator in this way:

enum PlatformID {
 None,
 Trinix,
 Unix,
 MacOS,
 Windows
}

PlatformID toPlatformID(string platform) {
 switch (platform.toLower()) {
 case "trinix":  return PlatformID.Trinix;
 case "unix":return PlatformID.Unix;
 case "macos":   return PlatformID.MacOS;
 case "windows": return PlatformID.Windows;
 default:return PlatformID.None;
 }
}

void opBinary(string op)(ref PlatformID plat, auto ref const string str)
if (op == "<<") {
 plat = toPlatformID(str);
}


void thisIsTest() {
 PlatformID id;
 id << "x86_64"; // this is not working
 id.opBinary!("<<")("test"); // but this works O.K.

}


Yuck. This should at the very least be opAssign instead.


operator overload for enum

2016-06-10 Thread Satoshi via Digitalmars-d-learn

Hello,
why operator overloading is not working as a static methods 
through the UFCS?


I need overload a << operator in this way:

enum PlatformID {
None,
Trinix,
Unix,
MacOS,
Windows
}

PlatformID toPlatformID(string platform) {
switch (platform.toLower()) {
case "trinix":  return PlatformID.Trinix;
case "unix":return PlatformID.Unix;
case "macos":   return PlatformID.MacOS;
case "windows": return PlatformID.Windows;
default:return PlatformID.None;
}
}

void opBinary(string op)(ref PlatformID plat, auto ref const 
string str) if (op == "<<") {

plat = toPlatformID(str);
}


void thisIsTest() {
PlatformID id;
id << "x86_64"; // this is not working
id.opBinary!("<<")("test"); // but this works O.K.

}


Re: What's wrong in this templatized operator overload ?

2015-10-22 Thread MobPassenger via Digitalmars-d-learn

On Thursday, 22 October 2015 at 05:17:29 UTC, Cauterite wrote:
On Thursday, 22 October 2015 at 04:25:01 UTC, MobPassenger 
wrote:
On Thursday, 22 October 2015 at 04:01:16 UTC, Mike Parker 
wrote:
On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger 
wrote:

code:
---
struct Foo
{
bool opIn_r(T)(T t){return false;}
}



This needs to be marked with const:

struct Foo
{
bool opIn_r(T)(T t) const {return false;}
}


what's the rationale ? what's guaranteed by the qualifier 
that's not already true without const ?


`const` just means the function won't mutate the object. 
`const` functions can be safely called on mutable, const and 
immutable objects. Non-`const` functions can only be called on 
mutable objects.


Thx for the explanations. By the way I knew that when const is 
applied to the return type it has to be surrounded between parens 
but so far I've never encountered the other case...And now I also 
remember why this attribte should rather be put at the right of 
the function declaration.


Re: What's wrong in this templatized operator overload ?

2015-10-21 Thread MobPassenger via Digitalmars-d-learn

On Thursday, 22 October 2015 at 04:01:16 UTC, Mike Parker wrote:
On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger 
wrote:

code:
---
struct Foo
{
bool opIn_r(T)(T t){return false;}
}



This needs to be marked with const:

struct Foo
{
bool opIn_r(T)(T t) const {return false;}
}


what's the rationale ? what's guaranteed by the qualifier that's 
not already true without const ?


Re: What's wrong in this templatized operator overload ?

2015-10-21 Thread Cauterite via Digitalmars-d-learn

On Thursday, 22 October 2015 at 04:25:01 UTC, MobPassenger wrote:

On Thursday, 22 October 2015 at 04:01:16 UTC, Mike Parker wrote:
On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger 
wrote:

code:
---
struct Foo
{
bool opIn_r(T)(T t){return false;}
}



This needs to be marked with const:

struct Foo
{
bool opIn_r(T)(T t) const {return false;}
}


what's the rationale ? what's guaranteed by the qualifier 
that's not already true without const ?


`const` just means the function won't mutate the object. `const` 
functions can be safely called on mutable, const and immutable 
objects. Non-`const` functions can only be called on mutable 
objects.


Re: What's wrong in this templatized operator overload ?

2015-10-21 Thread Mike Parker via Digitalmars-d-learn

On Thursday, 22 October 2015 at 03:19:49 UTC, MobPassenger wrote:

code:
---
struct Foo
{
bool opIn_r(T)(T t){return false;}
}



This needs to be marked with const:

struct Foo
{
bool opIn_r(T)(T t) const {return false;}
}


Re: What's wrong in this templatized operator overload ?

2015-10-21 Thread Vladimir Panteleev via Digitalmars-d-learn

On Thursday, 22 October 2015 at 03:21:35 UTC, MobPassenger wrote:
On Thursday, 22 October 2015 at 03:18:25 UTC, MobPassenger 
wrote:

code:


Plz don't reply, there's been a forum bug while posting.


What forum bug would that be?


What's wrong in this templatized operator overload ?

2015-10-21 Thread MobPassenger via Digitalmars-d-learn

code:
---
struct Foo
{
bool opIn_r(T)(T t){return false;}
}

static immutable Foo foo; // ouch
//static Foo foo; // OK

void main()
{
assert("a" !in foo);
}
---

output:
---
Error: template Foo.opIn_r cannot deduce function from argument 
types !()(string) immutable, candidates are:

runnable.Foo.opIn_r(T)(T t)
---


What's wrong in this templatized operator overload ?

2015-10-21 Thread MobPassenger via Digitalmars-d-learn

code:
---
struct Foo
{
bool opIn_r(T)(T t){return false;}
}

static immutable Foo foo; // ouch
//static Foo foo; // OK

void main()
{
assert("a" !in foo);
}


Re: What's wrong in this templatized operator overload ?

2015-10-21 Thread MobPassenger via Digitalmars-d-learn

On Thursday, 22 October 2015 at 03:18:25 UTC, MobPassenger wrote:

code:


Plz don't reply, there's been a forum bug while posting. Full 
post is here: 
http://forum.dlang.org/thread/kaqyeiakjunqoexos...@forum.dlang.org


Does it make sense to add attribute to operator overload functions ?

2014-10-25 Thread Jkpl via Digitalmars-d-learn
Everything is in the Q. I ask this because those functions are 
hidden behind symbols and keywords (+=, ~, in, etc.). It's not 
that obvious for a user who would write a custom type.


e.g:
---
struct myType
{
@safe nothrow opIndexAssign(t1 paramValue,t2 paramIndex){}
}
---

are the attributes necessary ? Are opXXX functions handled just 
like any other functs ? (traversal compat. of the attribs)


Re: Does it make sense to add attribute to operator overload functions ?

2014-10-25 Thread John Colvin via Digitalmars-d-learn

On Saturday, 25 October 2014 at 17:14:51 UTC, Jkpl wrote:
Everything is in the Q. I ask this because those functions are 
hidden behind symbols and keywords (+=, ~, in, etc.). It's not 
that obvious for a user who would write a custom type.


e.g:
---
struct myType
{
@safe nothrow opIndexAssign(t1 paramValue,t2 paramIndex){}
}
---

are the attributes necessary ? Are opXXX functions handled just 
like any other functs ? (traversal compat. of the attribs)


In every aspect they are ordinary functions, except they each 
have an additional unique way of being called (the relevant 
operator syntax).


In short, yes.


Re: Does it make sense to add attribute to operator overload functions ?

2014-10-25 Thread Jkpl via Digitalmars-d-learn

On Saturday, 25 October 2014 at 18:38:12 UTC, John Colvin wrote:

On Saturday, 25 October 2014 at 17:14:51 UTC, Jkpl wrote:
Everything is in the Q. I ask this because those functions are 
hidden behind symbols and keywords (+=, ~, in, etc.). It's not 
that obvious for a user who would write a custom type.


e.g:
---
struct myType
{
   @safe nothrow opIndexAssign(t1 paramValue,t2 paramIndex){}
}
---

are the attributes necessary ? Are opXXX functions handled 
just like any other functs ? (traversal compat. of the attribs)


In every aspect they are ordinary functions, except they each 
have an additional unique way of being called (the relevant 
operator syntax).


In short, yes.


Thx, A bit less confused by them now.



template operator overload

2013-11-27 Thread Namespace
Just out of curiosity: Is it possible to call an overloaded 
operator with a template type?


import std.stdio;

struct A {
void opIndex(T)(size_t index) {

}
}

void main() {
A a;
a.opIndex!int(0); // [1]
a!int[0]; // [2]
}


[1] works, but [2] fails.
How can I call opIndex with bracket syntax and a typename? Or is 
this not possible?


Re: template operator overload

2013-11-27 Thread Shammah Chancellor

On 2013-11-27 16:07:50 +, Namespace said:

Just out of curiosity: Is it possible to call an overloaded operator 
with a template type?


import std.stdio;

struct A {
void opIndex(T)(size_t index) {

}
}

void main() {
A a;
a.opIndex!int(0); // [1]
a!int[0]; // [2]
}


[1] works, but [2] fails.
How can I call opIndex with bracket syntax and a typename? Or is this 
not possible?


You need to simply use template deduction, and cast the parameter to 
what you're wanting to use between the brackets.


a[cast(int)0] (although zero is already an int);




Re: template operator overload

2013-11-27 Thread Namespace
On Wednesday, 27 November 2013 at 17:25:49 UTC, Shammah 
Chancellor wrote:

On 2013-11-27 16:07:50 +, Namespace said:

Just out of curiosity: Is it possible to call an overloaded 
operator with a template type?


import std.stdio;

struct A {
void opIndex(T)(size_t index) {

}
}

void main() {
A a;
a.opIndex!int(0); // [1]
a!int[0]; // [2]
}


[1] works, but [2] fails.
How can I call opIndex with bracket syntax and a typename? Or 
is this not possible?


You need to simply use template deduction, and cast the 
parameter to what you're wanting to use between the brackets.


a[cast(int)0] (although zero is already an int);


Inside the brackets I want an int. But I also want an extra type.

E.g.

A a;
a!string[4];



Re: template operator overload

2013-11-27 Thread Namespace

On Wednesday, 27 November 2013 at 17:47:13 UTC, bearophile wrote:

Namespace:


void main() {
A a;
a.opIndex!int(0); // [1]
a!int[0]; // [2]
}


[1] works, but [2] fails.
How can I call opIndex with bracket syntax and a typename? Or 
is this not possible?


I think that's not supported by D syntax. So if you want that, 
you need to use a syntax like a.at!int(0).


Bye,
bearophile


Too bad. Would have been really awesome.


Any trick for defining an operator overload in a different namespace?

2013-08-31 Thread Andrej Mitrovic
I'm trying to achieve the syntax opts[...] = 123, rather than using
the more direct this[...] = 123. I can use this code:

-
class C
{
this()
{
opts = Opts(this);
opts[foo] = 1;
}

struct Opts
{
C c;

void opIndexAssign(T)(T value, string option)
{
c.assign(option, value);
}
}

Opts opts;

private void assign(string option, int value)
{
}
}

void main()
{
auto c = new C();
}
-

But this explicitly stores the 'this' reference in the struct, I was
wondering if anyone knows of a trick to avoid having to do that. As
you can tell I just want a more convenient operator-based syntax over
calling the 'assign' method, but I don't want the operator to live in
the class space itself (because then I'd have to use this[...] =
that, which is a little quirky for my taste).


Re: Any trick for defining an operator overload in a different namespace?

2013-08-31 Thread Ali Çehreli

On 08/31/2013 03:07 AM, Andrej Mitrovic wrote:

 I'm trying to achieve the syntax opts[...] = 123, rather than using
 the more direct this[...] = 123. I can use this code:

 -
 class C
 {
  this()
  {
  opts = Opts(this);
  opts[foo] = 1;
  }

  struct Opts
  {
  C c;

  void opIndexAssign(T)(T value, string option)
  {
  c.assign(option, value);
  }
  }

  Opts opts;

  private void assign(string option, int value)
  {
  }
 }

 void main()
 {
  auto c = new C();
 }
 -

 But this explicitly stores the 'this' reference in the struct, I was
 wondering if anyone knows of a trick to avoid having to do that. As
 you can tell I just want a more convenient operator-based syntax over
 calling the 'assign' method, but I don't want the operator to live in
 the class space itself (because then I'd have to use this[...] =
 that, which is a little quirky for my taste).


This is the limitation of inner structs' not having an 'outer' 
reference, right?


Even if that were automatically available, it would still need a 
reference similar to your explicit 'c' reference. I think... :)


Ali



Re: Any trick for defining an operator overload in a different namespace?

2013-08-31 Thread Andrej Mitrovic
On 9/1/13, Ali Çehreli acehr...@yahoo.com wrote:
 This is the limitation of inner structs' not having an 'outer'
 reference, right?

Right, but this was just a workaround. Anyway I did just realize I can
use opDispatch for this:

-
class C
{
this()
{
this.opts[foo] = 1;
}

private auto opDispatch(string field : opts)()
{
return this;
}

private void opIndexAssign(T)(T value, string option)
{
assign(option, value);
}

private void assign(string option, int value)
{
}
}
-

It might seem a little funny that the only thing it does is just
returns 'this', which we already had. But I wanted to avoid writing
'this[foo] = 1;'. Well at the end of the day this may or may not be
what I wanted, since I still want to hide opDispatch. Oh well.. :)


static / global operator overload

2013-08-18 Thread Namespace
I can't find anything so I ask here: what was the decision to 
disallow static or global operator overloads?
In C++ you can declare operator overloads inside and outside of 
classes (the latter is more popular), so why wasn't this 
introduced in D also?


Thanks in advance. :)


Re: static / global operator overload

2013-08-18 Thread Ali Çehreli

On 08/18/2013 07:34 AM, Namespace wrote:

 In C++ you can declare operator overloads inside and outside of classes
 (the latter is more popular)

The latter is popular because a global operator takes advantage of 
implicit type conversions. A global operator+ allows using an int even 
on the left-hand side of the operator.


As a result, assuming that MyInt can be constructed from an int, when 
there is


// Assume this is defined outside of MyInt definition
MyInt operator+(MyInt lhs, MyInt rhs);

the expression

1 + MyInt(2)

is lowered to

operator+(MyInt(1), MyInt(2))

 so why wasn't this introduced in D also?

My guess is that there is no implicit construction of objects in D 
anyway so there wouldn't be that benefit.


Ali



Re: static / global operator overload

2013-08-18 Thread monarch_dodra

On Sunday, 18 August 2013 at 15:29:26 UTC, Ali Çehreli wrote:

On 08/18/2013 07:34 AM, Namespace wrote:

 In C++ you can declare operator overloads inside and outside
of classes
 (the latter is more popular)

The latter is popular because a global operator takes advantage 
of implicit type conversions. A global operator+ allows using 
an int even on the left-hand side of the operator.


As a result, assuming that MyInt can be constructed from an 
int, when there is


// Assume this is defined outside of MyInt definition
MyInt operator+(MyInt lhs, MyInt rhs);

the expression

1 + MyInt(2)

is lowered to

operator+(MyInt(1), MyInt(2))

 so why wasn't this introduced in D also?

My guess is that there is no implicit construction of objects 
in D anyway so there wouldn't be that benefit.


Ali


D defines the member opBinaryRight, which makes global 
operators un-needed.


//
struct S
{
void opBinary(alias s)(int i)
if (s == +)
{
writeln(s);
}
void opBinaryRight(alias s)(int i)
if (s == +)
{
return this + i;
}
}

void main()
{
S s;
s + 5;
5 + s;
}
//

Doing this also helps avoid poluting the global name-space with 
operators.


Re: static / global operator overload

2013-08-18 Thread Namespace

On Sunday, 18 August 2013 at 15:29:26 UTC, Ali Çehreli wrote:

On 08/18/2013 07:34 AM, Namespace wrote:

 In C++ you can declare operator overloads inside and outside
of classes
 (the latter is more popular)

The latter is popular because a global operator takes advantage 
of implicit type conversions. A global operator+ allows using 
an int even on the left-hand side of the operator.


As a result, assuming that MyInt can be constructed from an 
int, when there is


// Assume this is defined outside of MyInt definition
MyInt operator+(MyInt lhs, MyInt rhs);

the expression

1 + MyInt(2)

is lowered to

operator+(MyInt(1), MyInt(2))

 so why wasn't this introduced in D also?

My guess is that there is no implicit construction of objects 
in D anyway so there wouldn't be that benefit.


Ali


It's also preferred (at least by me) because such methods don't 
have to be in a class/struct and blows it up. They don't effect 
the class/struct and thanks to UFCS we still could call them like 
member methods.
So IMO because they have no effect in a class/struct they 
shouldn't be there.


Compare:

bool opEquals(ref const A a) { ... } inside of struct A

versus:

bool opEquals(ref const A lhs, ref const A rhs) { ... }

I would prefer the last one.

But I would like to see an official thread for this, if any 
exist. Do you know one? I'm just startled that D follows this 
way. :)


Re: static / global operator overload

2013-08-18 Thread monarch_dodra

On Sunday, 18 August 2013 at 21:23:05 UTC, Namespace wrote:

On Sunday, 18 August 2013 at 15:29:26 UTC, Ali Çehreli wrote:

On 08/18/2013 07:34 AM, Namespace wrote:

 In C++ you can declare operator overloads inside and outside
of classes
 (the latter is more popular)

The latter is popular because a global operator takes 
advantage of implicit type conversions. A global operator+ 
allows using an int even on the left-hand side of the operator.


As a result, assuming that MyInt can be constructed from an 
int, when there is


   // Assume this is defined outside of MyInt definition
   MyInt operator+(MyInt lhs, MyInt rhs);

the expression

   1 + MyInt(2)

is lowered to

   operator+(MyInt(1), MyInt(2))

 so why wasn't this introduced in D also?

My guess is that there is no implicit construction of objects 
in D anyway so there wouldn't be that benefit.


Ali


It's also preferred (at least by me) because such methods don't 
have to be in a class/struct and blows it up. They don't effect 
the class/struct and thanks to UFCS we still could call them 
like member methods.
So IMO because they have no effect in a class/struct they 
shouldn't be there.


Compare:

bool opEquals(ref const A a) { ... } inside of struct A

versus:

bool opEquals(ref const A lhs, ref const A rhs) { ... }

I would prefer the last one.

But I would like to see an official thread for this, if any 
exist. Do you know one? I'm just startled that D follows this 
way. :)


The possibility of static operator was raised, specifically for 
opDollar, in std.range, for the possibility of it automatically 
resolving to length.


Reception for *just* this was kind of cold. I remember it being 
downright hostile for UFCS operators in general.


The full conversation is here:
http://d.puremagic.com/issues/show_bug.cgi?id=7177
Note that while UFCS was discussed, it wasn't the root of the 
discussion :/


Re: parse json-string - operator overload error

2012-05-17 Thread Jarl André

On Wednesday, 1 December 2010 at 08:17:37 UTC, zusta wrote:

Hey guys,

I'm trying to read a JSON-formated file. The parsing of the 
file seems to be

correct, but I always get the following error:

Error: no [] operator overload for type JSONValue.

For testing purposes, I also tried the code of
http://www.digitalmars.com/d/archives/digitalmars/D/std.json_API_improvement_
-_Request_for_code_review_117261.html#N117302 without success 
(same error).


My currently code looks like this:

import std.stdio : writeln;
import std.json;
import std.stream;
import std.conv;

void main(string[] args) {

File f = new File(test.json, FileMode.In);
string content = to!(string)(f.readString(f.available()));
JSONValue t = parseJSON(content);
writeln(t[test]);
f.close();

}

I hope anyone can help to find out what's wrong with the code 
above.


Assuming the file reading was not the fault:

string content = { \test\: \1\  };
JSONValue[string] t = parseJSON(content).object;
writeln(t[test].str);

This is one way to access the data in the file.


primitive type operator overload

2012-04-20 Thread dominic jones

Hello,

I want to overload a primitive type operator so that I can do 
something like


double a;
myStruct b;
writeln(a + b);

but have no idea how to do it. Something similar(?) is already 
implemented in the language, i.e.


double x;
double[] y;
writeln(x + y);

but after searching the dmd2/src, what I found didn't offer any 
help.


-Dominic Jones


Re: primitive type operator overload

2012-04-20 Thread bearophile

Dominic Jones:

I want to overload a primitive type operator so that I can do 
something like


double a;
myStruct b;
writeln(a + b);


You can't overload the operator of a primitive, but binary 
operators come in left and right versions:

http://dlang.org/operatoroverloading.html#Binary

a.opBinary!(op)(b)
b.opBinaryRight!(op)(a)

so adding an inverse + operator inside myStruct is possible.

Bye,
bearophile


Re: primitive type operator overload

2012-04-20 Thread Mafi

Am 20.04.2012 18:41, schrieb bearophile:

Dominic Jones:


I want to overload a primitive type operator so that I can do
something like

double a;
myStruct b;
writeln(a + b);


You can't overload the operator of a primitive, but binary operators
come in left and right versions:

...


Bye,
bearophile


Shouldn't a consequence of UFCS be that you can overload binary 
operators for primitives, as should global overloads (like in C++).


Re: primitive type operator overload

2012-04-20 Thread H. S. Teoh
On Fri, Apr 20, 2012 at 07:12:41PM +0200, Mafi wrote:
 Am 20.04.2012 18:41, schrieb bearophile:
 Dominic Jones:
 
 I want to overload a primitive type operator so that I can do
 something like
 
 double a;
 myStruct b;
 writeln(a + b);
 
 You can't overload the operator of a primitive, but binary operators
 come in left and right versions:
 ...
 
 Bye,
 bearophile
 
 Shouldn't a consequence of UFCS be that you can overload binary
 operators for primitives, as should global overloads (like in C++).

UFCS only kicks in if no matching method is found for the given type. So
UFCS can be used to provide default implementations for when an
operator is not defined for a given type, but the operator defined by
the type takes precedence over UFCS.


T

-- 
How are you doing? Doing what?


parse json-string - operator overload error

2010-12-01 Thread zusta
Hey guys,

I'm trying to read a JSON-formated file. The parsing of the file seems to be
correct, but I always get the following error:

Error: no [] operator overload for type JSONValue.

For testing purposes, I also tried the code of
http://www.digitalmars.com/d/archives/digitalmars/D/std.json_API_improvement_
-_Request_for_code_review_117261.html#N117302 without success (same error).

My currently code looks like this:

import std.stdio : writeln;
import std.json;
import std.stream;
import std.conv;

void main(string[] args) {

File f = new File(test.json, FileMode.In);
string content = to!(string)(f.readString(f.available()));
JSONValue t = parseJSON(content);
writeln(t[test]);
f.close();

}

I hope anyone can help to find out what's wrong with the code above.