Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
September 01, 2011 opDispatch shadowing toString - feature or bug? | ||||
---|---|---|---|---|
| ||||
Greetings. I've been playing around with opDispatch and toString methods and I found strange behavior. Example: import std.stdio; struct Test { string opDispatch( string key )() { return "I am dispatching in struct!"; } string toString() { return "I am Test struct!"; } } class Test2 { string opDispatch( string key )() { return "I am dispatching in class!"; } string toString() { return "I am Test class!"; } } void main() { Test test = Test(); writeln ( test.s ); // I am dispatching in struct! writeln ( test.s() ); // I am dispatching in struct! writeln ( test ); // NOTHING :( But should return "I am Test struct!" Test2 test2 = new Test2(); writeln ( test2.s ); // I am dispatching in class! writeln ( test2.s() ); // I am dispatching in class! writeln ( test2 ); // NOTHING :( But should return "I am Test class!" } Is it a feature or a bug? Best regards, Damian Ziemba |
September 01, 2011 Re: opDispatch shadowing toString - feature or bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Damian Ziemba | Try to create the method: const void toString(void delegate(const(char)[]) sink, string formatString) { sink(toString()); } |
September 01, 2011 Re: opDispatch shadowing toString - feature or bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christophe | On Thu, 01 Sep 2011 07:56:49 +0000, Christophe wrote:
> Try to create the method:
>
> const void toString(void delegate(const(char)[]) sink, string
> formatString) {
> sink(toString());
> }
Adding it as it is results in compiler error:
./quick.d(30): Error: function quick.Test2.toString () is not c
allable using argument types () const
./quick.d(30): Error: expected 2 function arguments, not 0
./quick.d(30): Error: cannot implicitly convert expression
(this.toString()) of type void to const(char)[]
Removing const from begging allows it to compile. But it doesn't change anything. Still "nothing" appears ;-)
|
September 01, 2011 Re: opDispatch shadowing toString - feature or bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Damian Ziemba | On 09/01/2011 09:34 AM, Damian Ziemba wrote:
> Greetings.
>
> I've been playing around with opDispatch and toString methods and I found
> strange behavior.
>
> Example:
>
> import std.stdio;
>
> struct Test
> {
> string opDispatch( string key )()
> {
> return "I am dispatching in struct!";
> }
>
> string toString()
> {
> return "I am Test struct!";
> }
> }
>
> class Test2
> {
> string opDispatch( string key )()
> {
> return "I am dispatching in class!";
> }
>
> string toString()
> {
> return "I am Test class!";
> }
> }
>
> void main()
> {
> Test test = Test();
> writeln ( test.s ); // I am dispatching in struct!
> writeln ( test.s() ); // I am dispatching in struct!
> writeln ( test ); // NOTHING :( But should return "I am
> Test struct!"
>
> Test2 test2 = new Test2();
> writeln ( test2.s ); // I am dispatching in class!
> writeln ( test2.s() ); // I am dispatching in class!
> writeln ( test2 ); // NOTHING :( But should return "I am
> Test class!"
> }
>
> Is it a feature or a bug?
>
> Best regards,
> Damian Ziemba
>
static assert(isInputRange!Test);
static assert(isInputRange!Test2);
toString is not shadowed, but the implementation of writeln assumes that your types are an InputRange (they provide, by the means of opDispatch, front(), empty() and popFront())
The fact that writeln([]); prints a new line instead of "[]" is a bug that has already been taken care of in a pull request afaik.
This specific problem can be solved by making your types not follow the InputRange interface, by putting an appropriate constraint on your opDispatch.
import std.stdio;
struct Test
{
string opDispatch( string key )() if(key!="popFront")
{
return "I am dispatching in struct!";
}
string toString()
{
return "I am Test struct!";
}
}
class Test2
{
string opDispatch( string key )() if(key!="popFront")
{
return "I am dispatching in class!";
}
string toString()
{
return "I am Test class!";
}
}
void main()
{
Test test = Test();
writeln ( test.s ); // I am dispatching in struct!
writeln ( test.s() ); // I am dispatching in struct!
writeln ( test ); //I am Test struct!
Test2 test2 = new Test2();
writeln ( test2.s ); // I am dispatching in class!
writeln ( test2.s() ); // I am dispatching in class!
writeln ( test2 ); // I am Test class!
}
|
September 01, 2011 Re: opDispatch shadowing toString - feature or bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Thu, 01 Sep 2011 13:59:29 +0200, Timon Gehr wrote: > static assert(isInputRange!Test); > static assert(isInputRange!Test2); > > toString is not shadowed, but the implementation of writeln assumes that > your types are an InputRange (they provide, by the means of opDispatch, > front(), empty() and popFront()) > > The fact that writeln([]); prints a new line instead of "[]" is a bug that has already been taken care of in a pull request afaik. > > This specific problem can be solved by making your types not follow the InputRange interface, by putting an appropriate constraint on your opDispatch. > > > import std.stdio; > > struct Test > { > string opDispatch( string key )() if(key!="popFront") { > return "I am dispatching in struct!"; > } > > string toString() > { > return "I am Test struct!"; > } > } > > class Test2 > { > string opDispatch( string key )() if(key!="popFront") { > return "I am dispatching in class!"; > } > > string toString() > { > return "I am Test class!"; > } > } > > void main() > { > Test test = Test(); > writeln ( test.s ); // I am dispatching in struct! writeln ( test.s() > ); // I am dispatching in struct! writeln ( test ); //I am Test struct! > > Test2 test2 = new Test2(); > writeln ( test2.s ); // I am dispatching in class! writeln ( test2.s() > ); // I am dispatching in class! writeln ( test2 ); // I am Test class! > } Yes, this fix the problem. Hmm, after all its a bit loose of a keyword, becouse I can't use anymore test.popFront. For example if class acts as a storage device class Storage { string[ string ] vars; string opDispatch( string key )() if ( key != "popFront" ) { if ( key in vars ) return vars[ key ]; else return ""; } string toString() { // implement me } } auto storage = new Storage; storage.vars["test"] = "I'm a test!"; storage.vars["popFront"] = "I'm a poping around! :D"; writeln( storage.test ); // I'm a test! writeln( storage.popFront ); // error Ofcours, in opDispatch I can use empty or front instead of popFront but it is still loose of one keyword. Looks like it's a loose I have to take :-) Thank you very much for reply! Best regards, Damian Ziemba |
September 01, 2011 Re: opDispatch shadowing toString - feature or bug? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Damian Ziemba | On 09/02/2011 12:09 AM, Damian Ziemba wrote:
> On Thu, 01 Sep 2011 13:59:29 +0200, Timon Gehr wrote:
>
>> static assert(isInputRange!Test);
>> static assert(isInputRange!Test2);
>>
>> toString is not shadowed, but the implementation of writeln assumes that
>> your types are an InputRange (they provide, by the means of opDispatch,
>> front(), empty() and popFront())
>>
>> The fact that writeln([]); prints a new line instead of "[]" is a bug
>> that has already been taken care of in a pull request afaik.
>>
>> This specific problem can be solved by making your types not follow the
>> InputRange interface, by putting an appropriate constraint on your
>> opDispatch.
>>
>>
>> import std.stdio;
>>
>> struct Test
>> {
>> string opDispatch( string key )() if(key!="popFront") {
>> return "I am dispatching in struct!";
>> }
>>
>> string toString()
>> {
>> return "I am Test struct!";
>> }
>> }
>>
>> class Test2
>> {
>> string opDispatch( string key )() if(key!="popFront") {
>> return "I am dispatching in class!";
>> }
>>
>> string toString()
>> {
>> return "I am Test class!";
>> }
>> }
>>
>> void main()
>> {
>> Test test = Test();
>> writeln ( test.s ); // I am dispatching in struct! writeln
> ( test.s()
>> ); // I am dispatching in struct! writeln ( test ); //I am Test
> struct!
>>
>> Test2 test2 = new Test2();
>> writeln ( test2.s ); // I am dispatching in class! writeln
> ( test2.s()
>> ); // I am dispatching in class! writeln ( test2 ); // I am Test
> class!
>> }
>
> Yes, this fix the problem.
>
> Hmm, after all its a bit loose of a keyword, becouse I can't use anymore
> test.popFront. For example if class acts as a storage device
>
> class Storage
> {
> string[ string ] vars;
>
> string opDispatch( string key )() if ( key != "popFront" )
> {
> if ( key in vars ) return vars[ key ];
> else return "";
> }
>
> string toString() { // implement me
> }
> }
>
> auto storage = new Storage;
> storage.vars["test"] = "I'm a test!";
> storage.vars["popFront"] = "I'm a poping around! :D";
>
> writeln( storage.test ); // I'm a test!
> writeln( storage.popFront ); // error
>
> Ofcours, in opDispatch I can use empty or front instead of popFront but
> it is still loose of one keyword.
>
> Looks like it's a loose I have to take :-)
>
> Thank you very much for reply!
>
> Best regards,
> Damian Ziemba
template isInputRange(R)
{
enum bool isInputRange = is(typeof(
{
R r; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
}()));
}
With the next DMD release, you could use a struct with a disabled default constructor. Because it cannot be defined, the first line will fail, and isInputRange will be false.
Basically, anything that will make
R r; // can define a range object
if (r.empty) {} // can test for empty
r.popFront(); // can invoke popFront()
auto h = r.front; // can get the front of the range
fail to compile is good enough. Eg, if r.empty is not convertible to bool.
|
Copyright © 1999-2021 by the D Language Foundation