| Thread overview | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 18, 2014 Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
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?
| ||||
December 18, 2014 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jay Pinkman | 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. | |||
December 18, 2014 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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. | |||
January 03, 2015 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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();
}
| |||
January 03, 2015 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Darrell | 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();
> }
| |||
January 03, 2015 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Darrell | 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));
}
| |||
January 03, 2015 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Darrell | 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));
}
| |||
January 03, 2015 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Darrell | 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
| |||
January 03, 2015 Re: Weird UFC and opCall issues | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply