Jump to page: 1 2
Thread overview
Debug help - opDispatch - unknown member function
1 day ago
Brother Bill
1 day ago
monkyyy
1 day ago
Brother Bill
1 day ago
monkyyy
15 hours ago
Brother Bill
14 hours ago
Brother Bill
12 hours ago
monkyyy
16 hours ago
Dejan Lekic
14 hours ago
Brother Bill
14 hours ago
Dejan Lekic
11 hours ago
IchorDev
12 hours ago
monkyyy
6 hours ago
monkyyy
1 day ago

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

This states: "Any unknown member function call to that type is passed to opDispatch, passing the unknown member function's name as a string template parameter."

So I tried that. But the compiler didn't like it.
How should I play the game of passing in an unknown member function name?

import std.stdio;

void main()
{
	CallLogger!C l;
	l.callA(1, 2);
	l.callB("ABC");
	l.callHome("foo", "bar");   // Fails here
}

struct C
{
	void callA(int i, int j)
	{
	}

	void callB(string s)
	{

	}
}

struct CallLogger(C)
{
	C content;
	void opDispatch(string name, T...)(T vals)
	{
		writeln("called ", name);
		mixin("content." ~ name)(vals);
	}
}

Console output:

c:\dev\D\D_templates_tutorial\toy1\source\app.d(8): Error: no property `callHome` for `l` of type `app.CallLogger!(C)`
    l.callHome("foo", "bar");
     ^
1 day ago

On Tuesday, 9 September 2025 at 00:40:31 UTC, Brother Bill wrote:

>

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

This states: "Any unknown member function call to that type is passed to opDispatch, passing the unknown member function's name as a string template parameter."

[...]

you didnt define "callhome" so the the mixin fails, this propagates a "__error" or something, and opDispatch when it contains an error doesnt pass it up the stack

1 day ago

On Tuesday, 9 September 2025 at 00:45:00 UTC, monkyyy wrote:

>

On Tuesday, 9 September 2025 at 00:40:31 UTC, Brother Bill wrote:

>

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

This states: "Any unknown member function call to that type is passed to opDispatch, passing the unknown member function's name as a string template parameter."

[...]

you didnt define "callhome" so the the mixin fails, this propagates a "__error" or something, and opDispatch when it contains an error doesnt pass it up the stack

Then I'm not clear what an "unknown" member function name means.

Kindly provide an example.

1 day ago

On Tuesday, 9 September 2025 at 01:08:41 UTC, Brother Bill wrote:

>

On Tuesday, 9 September 2025 at 00:45:00 UTC, monkyyy wrote:

>

On Tuesday, 9 September 2025 at 00:40:31 UTC, Brother Bill wrote:

>

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

This states: "Any unknown member function call to that type is passed to opDispatch, passing the unknown member function's name as a string template parameter."

[...]

you didnt define "callhome" so the the mixin fails, this propagates a "__error" or something, and opDispatch when it contains an error doesnt pass it up the stack

Then I'm not clear what an "unknown" member function name means.

Kindly provide an example.

import std;
struct Vector(int N,T,string fields){
	static foreach(I;0..N){
		mixin("T "~fields[I]~";");
	}
	auto opDispatch(string __s__)(){//I suggest a habit of avoiding simple names when generating mixin code
		return mixin((){
			string output="tuple(";
			foreach(C;__s__){
				output~=C;
				output~=',';
			}
			output~=")";
			return output;
		}());
	}
}
unittest{
	Vector!(3,int,"xyz") foo;
	foo.x=5;
	foo.y=3;
	foo.yx.writeln;
	Vector!(4,ubyte,"rgba") bar;
	bar.bgr.writeln;
}
16 hours ago

On Tuesday, 9 September 2025 at 00:40:31 UTC, Brother Bill wrote:

>

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

This states: "Any unknown member function call to that type is passed to opDispatch, passing the unknown member function's name as a string template parameter."

So I tried that. But the compiler didn't like it.
How should I play the game of passing in an unknown member function name?

Hopefully this slightly modified, and commented version of your original code will
help you understand why your mixin is failing:

import std.stdio;

void main() {
    CallLogger!C l;
    l.callA(1, 2);
    l.callB("ABC");

    // CallLogger does not have method called "callHome", but it has opDispatch, so
    // the compiler will lower this down to l.opDispatch("callHome", "foo", "bar")
    l.callHome("foo", "bar");
}

struct C {
    void callA(int i, int j) {
    }

    void callB(string s) {
    }

    // Your mixin generates code that calls C.callHome which did not exist
    void callHome(string a, string b) {
        writeln(a, "/", b);
    }
}

struct CallLogger(C) {
    C content;
    void opDispatch(string name, T...)(T vals) {
        writeln("called ", name);

        // Now it works, because C now has callHome method
        mixin("content." ~ name)(vals);
    }
}
15 hours ago

On Tuesday, 9 September 2025 at 01:24:59 UTC, monkyyy wrote:

>
import std;
struct Vector(int N,T,string fields){
	static foreach(I;0..N){
		mixin("T "~fields[I]~";");
	}
	auto opDispatch(string __s__)(){//I suggest a habit of avoiding simple names when generating mixin code
		return mixin((){
			string output="tuple(";
			foreach(C;__s__){
				output~=C;
				output~=',';
			}
			output~=")";
			return output;
		}());
	}
}
unittest{
	Vector!(3,int,"xyz") foo;
	foo.x=5;
	foo.y=3;
	foo.yx.writeln;
	Vector!(4,ubyte,"rgba") bar;
	bar.bgr.writeln;
}

I simplified your example, and manually expanded opDispatch so D newbies can grok it.
Please explain the opDispatch IIFE and why no semicolon needed at the end.

import std;

// Comment out yx() xor opDispatch()

struct Vector(int N, T, string fields){
	int x;
	int y;
	int z;

	// manual expansion of opDispatch
	// auto yx() {
	// 	string output = "tuple(";
	// 	foreach (char scv; "yx") {
	// 		output ~= scv;
	// 		output ~= ",";
	// 	}
	// 	output ~= ")";
	// 	writeln(output);			// This is not in opDispatch()
	// 	return tuple(3, 5);         // Hack to return same result
	// }

	// I suggest a habit of avoiding simple names when generating mixin code
	auto opDispatch(string __s__)() {  // IIFE
		writeln("__s__: ", __s__);

		return mixin(() {
			string output = "tuple(";
			foreach (C; __s__){
				output ~= C;
				output ~= ',';
			}
			output ~= ")";
			return output;
		} ());
	}
}

void main() {
	Vector!(3, int, "xyz") foo;
	foo.x = 5;		// Standard assignment to known member
	foo.y = 3;		// Standard assignment to known member
	foo.yx.writeln;	// yx not a member of Vector, so opDispatch is called
}}

Console output:

__s__: yx
Tuple!(int, int)(3, 5)
14 hours ago

On Tuesday, 9 September 2025 at 01:24:59 UTC, monkyyy wrote:

>
// I suggest a habit of avoiding simple names when generating mixin code

Please provide an example where providing simple names causes 'trouble'.

14 hours ago

On Tuesday, 9 September 2025 at 09:59:40 UTC, Dejan Lekic wrote:

>

Hopefully this slightly modified, and commented version of your original code will
help you understand why your mixin is failing:

import std.stdio;

void main() {
    CallLogger!C l;
    l.callA(1, 2);
    l.callB("ABC");

    // CallLogger does not have method called "callHome", but it has opDispatch, so
    // the compiler will lower this down to l.opDispatch("callHome", "foo", "bar")
    l.callHome("foo", "bar");
}

struct C {
    void callA(int i, int j) {
    }

    void callB(string s) {
    }

    // Your mixin generates code that calls C.callHome which did not exist
    void callHome(string a, string b) {
        writeln(a, "/", b);
    }
}

struct CallLogger(C) {
    C content;
    void opDispatch(string name, T...)(T vals) {
        writeln("called ", name);

        // Now it works, because C now has callHome method
        mixin("content." ~ name)(vals);
    }
}

When commenting out the callHome() in struct C, it fails.
Obviously if callHome() is explicitly created, it works.

import std.stdio;

void main() {
    CallLogger!C l;
    l.callA(1, 2);
    l.callB("ABC");

    // CallLogger does not have method called "callHome", but it has opDispatch, so
    // the compiler will lower this down to l.opDispatch("callHome", "foo", "bar")
    l.callHome("foo", "bar");
}

struct C {
    void callA(int i, int j) {
    }

    void callB(string s) {
    }

    // Your mixin generates code that calls C.callHome which did not exist
    // void callHome(string a, string b) {
    //     writeln(a, "/", b);
    // }
}

struct CallLogger(C) {
    C content;
    void opDispatch(string name, T...)(T vals) {
        writeln("called ", name);

        // Now it works, because C now has callHome method
        mixin("content." ~ name)(vals);
    }
}

Console contents:

c:\dev\D\D_templates_tutorial\toy1\source\app.d(10): Error: no property `callHome` for `l` of type `app.CallLogger!(C)`
    l.callHome("foo", "bar");
     ^
14 hours ago

On Tuesday, 9 September 2025 at 12:04:07 UTC, Brother Bill wrote:

>

When commenting out the callHome() in struct C, it fails.
Obviously if callHome() is explicitly created, it works.

If C does not have callHome() method, then

    mixin("content." ~ name)(vals);

will simply fail, because that line effectively generates this code:

    content.callHome("foo", "bar");

Since content is of type C, which does not have callHome method, it will fail, and is expected to fail. Sorry I can't think of a better explanation than what I tried in my previous post... Since I can't come up with a better explanation I will stop writing in this thread. Good luck!

12 hours ago

On Tuesday, 9 September 2025 at 11:57:54 UTC, Brother Bill wrote:

>

On Tuesday, 9 September 2025 at 01:24:59 UTC, monkyyy wrote:

>
// I suggest a habit of avoiding simple names when generating mixin code

Please provide an example where providing simple names causes 'trouble'.

import std;
struct Vector(int N,T,string fields){
	static foreach(I;0..N){
		mixin("T "~fields[I]~";");
	}
	auto opDispatch(string s)(){//I suggest a habit of avoiding simple names when generating mixin code
		return mixin((){
			string output="tuple(";
			foreach(C;s){
				output~=C;
				output~=',';
			}
			output~=")";
			return output;
		}());
	}
}
unittest{
	Vector!(4,int,"xyzs") foo;
	foo.x=5;
	foo.y=3;
        foo.s=7;
	assert(foo.sx==tuple(7,5));
}
« First   ‹ Prev
1 2