www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Weird UFC and opCall issues

reply "Jay Pinkman" <jaypinkman hotmail.com> writes:
void main () {
     struct X {
         string x;

         void opCall (string y) {
             import std.stdio;
             writeln("%s %s!", x, y);
         }
     }

     auto x = X("hello");
     "world".x;
}

source/main.d(12): Error: need 'this' for 'opCall' of type 
'void(string y)'
source/main.d(13): Error: no property 'x' for type 'string'

but why?
Dec 17 2014
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 18 December 2014 at 02:42:32 UTC, Jay Pinkman wrote:
 source/main.d(12): Error: need 'this' for 'opCall' of type 
 'void(string y)'
D doesn't have a really clean separation between static and non-static methods. It sees an opCall and thinks you're trying to call it, but since it isn't static, it complains you don't have a this.
 source/main.d(13): Error: no property 'x' for type 'string'
I don't think UFCS works with structs nor local variables anyway, so this error makes sense to me.
Dec 17 2014
next sibling parent "Jay Pinkman" <jaypinkman hotmail.com> writes:
On Thursday, 18 December 2014 at 02:45:01 UTC, Adam D. Ruppe 
wrote:
 D doesn't have a really clean separation between static and 
 non-static methods.
hmm.. i thought that's what 'static' is for.
 It sees an opCall and thinks you're trying to call it, but 
 since it isn't static, it complains you don't have a this.
so it's bug i should report or some idiosyncracy?
 I don't think UFCS works with structs nor local variables 
 anyway, so this error makes sense to me.
i guess i should request this. in my other code i use a struct to represent a transformation so it makes perfect sense to use it in UFCS fashion.
Dec 17 2014
prev sibling parent reply "Darrell" <dgallion1 gmail.com> writes:
Fails with:
     t.d(34): Error: need 'this' for 'opCall' of type 'int()'

Also opCall seems to be required to create a range.

class Test
{
   int opCall()
   {
     return 1;
   }

    property int front()
   {
     return 2;
   }

   void popFront()
   {
   }

    property bool empty()
   {
     return false;
   }

};

void main(){
   ubyte [] p1;
   Test();
}
Jan 03 2015
next sibling parent reply "Darrell" <dgallion1 gmail.com> writes:
Ooops.
Test() wasn't valid.
Still working to create a range object that iterates over an 
internal data struct. But this was may error.


On Saturday, 3 January 2015 at 20:26:41 UTC, Darrell wrote:
 Fails with:
     t.d(34): Error: need 'this' for 'opCall' of type 'int()'

 Also opCall seems to be required to create a range.

 class Test
 {
   int opCall()
   {
     return 1;
   }

    property int front()
   {
     return 2;
   }

   void popFront()
   {
   }

    property bool empty()
   {
     return false;
   }

 };

 void main(){
   ubyte [] p1;
   Test();
 }
Jan 03 2015
parent reply "Darrell" <dgallion1 gmail.com> writes:
Seems when creating your own ranges they can't be a class.
Must be a struct or Segmentation fault (core dumped) will follow.

This works as long as Test is a struct.

struct Test
{
    property int front()
   {
     return 2;
   }

   void popFront()
   {
   }

   enum bool empty = false;
};

static assert(isInputRange!Test);

void mainx(){
   Test x;
   writeln(x.take(1));
}
Jan 03 2015
parent ted <foo bar.com> writes:
Darrell wrote:

 Seems when creating your own ranges they can't be a class.
 Must be a struct or Segmentation fault (core dumped) will follow.
 
 This works as long as Test is a struct.
 
 struct Test
 {
     property int front()
    {
      return 2;
    }
 
    void popFront()
    {
    }
 
    enum bool empty = false;
 };
 
 static assert(isInputRange!Test);
 
 void mainx(){
    Test x;
    writeln(x.take(1));
 }
With classes, you need to create an instance, so (adjusting some of your previous code) this works: import std.range; import std.stdio; class Test { property int front() { return 2; } void popFront() { } property bool empty() { return false; } }; static assert(isInputRange!Test); void main(){ ubyte [] p1; Test myTest = new Test(); writeln(myTest.take(1)); }
Jan 03 2015
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 01/03/2015 12:26 PM, Darrell wrote:

 Fails with:
      t.d(34): Error: need 'this' for 'opCall' of type 'int()'

 Also opCall seems to be required to create a range.
D has a feature that does not exists e.g. in C++: You can call the type itself as a function. The 'Test()' syntax is a call to that type's static opCall().
 class Test
 {
    int opCall()
    {
      return 1;
    }
Not being static, that would require an instance of the Test class.
     property int front()
    {
      return 2;
    }
You may want to define that member function 'const' as well.
    void popFront()
    {
    }

     property bool empty()
    {
      return false;
    }
That can be 'const' as well.
 };
D does not require that semicolon.
 void main(){
    ubyte [] p1;
    Test();
 }
I am removing the opCall and assuming that you actually want a ubyte I am returning a ubyte from front(). Also note the almost-mandatory-with-ranges convenience function 'test()' below, which hides the invocation of 'new': class Test { property ubyte front() { return 2; } void popFront() { } property bool empty() { return false; } } Test test() { return new Test(); } /* Alternatively, you can move test() inside Test as a static opCall: static Test opCall() { return new Test(); } Then, the syntax in main could be ubyte [] p1 = Test().take(3).array; */ import std.stdio; import std.range; void main(){ ubyte [] p1 = test().take(3).array; assert(p1 == [ 2, 2, 2 ]); } Ali
Jan 03 2015
parent "Darrell" <dgallion1 gmail.com> writes:
Thanks for the feedback.

 With classes, you need to create an instance
Need to read up classes vs struct. This bit of syntax was very intresting. /* Alternatively, you can move test() inside Test as a static opCall: static Test opCall() { return new Test(); } Then, the syntax in main could be ubyte [] p1 = Test().take(3).array; */ Very impressed with D and starting a new job. Might be able to use it.
Jan 03 2015