Thread overview
with statement not triggering opDispatch?
Feb 05, 2015
Alex Parrill
Feb 05, 2015
Meta
Feb 05, 2015
Meta
Feb 06, 2015
Alex Parrill
February 05, 2015
DMD does not seem to consider `opDispatch` when looking up variables in a `with` block, or . Is this intentional, or a bug/oversight?

For example:

	import std.typecons;
	import std.stdio;

	struct MyStruct {
		auto opDispatch(string name)() {
			return name~"!";
		}
	}

	void main() {
		auto obj = MyStruct();
		with(obj)
			writeln(helloworld());
	}

Fails to run with the following error:

	$ rdmd test.d
	test.d(14): Error: undefined identifier helloworld
	Failed: ["dmd", "-v", "-o-", "test.d", "-I."]

Even though `helloworld` should be "defined", by way of the `opDispatch` template.

This also occurs when looking up identifiers in methods, when not prefixing the identifiers with `this`:

	import std.typecons;
	import std.stdio;

	struct MyStruct {
		auto opDispatch(string name)() {
			return name~"!";
		}

		void run() {
			writeln(helloworld()); // Error: no identifier `helloworld`
		}
	}

	void main() {
		auto obj = MyStruct();
		obj.run();
	}

I can work around it via introducing a wrapper struct that contains the wrapped struct and uses `alias this` on it, which fixes the identifier resolution with methods, but not with `with`:

	import std.typecons;
	import std.stdio;

	struct MyStruct {
		auto opDispatch(string name)() {
			return name~"!";
		}
	}

	struct MyStructWrapper {
		MyStruct __mystruct;
		alias __mystruct this;

		void run() {
			writeln(helloworld()); // Prints "helloworld!"
		}
	}

	void main() {
		auto obj = MyStructWrapper();
		obj.run();
		with(obj) writeln(helloworld()); // Still fails
	}

My use case for this is a D implementation of Mustache that compiles templates at compile-time, and can be used with arbitrary objects. The structure maintains the context stack (stored as a tuple), with `opDispatch` forwarding accesses to the first object in the stack that contains the named identifier. The tag content would be retrieved like `with(context) return mixin(tag_content);`, so that `{{helloworld}}` would generate `with(context) return helloworld;`.
February 05, 2015
On Thursday, 5 February 2015 at 16:27:01 UTC, Alex Parrill wrote:
> DMD does not seem to consider `opDispatch` when looking up variables in a `with` block, or . Is this intentional, or a bug/oversight?
>
> For example:
>
> 	import std.typecons;
> 	import std.stdio;
>
> 	struct MyStruct {
> 		auto opDispatch(string name)() {
> 			return name~"!";
> 		}
> 	}
>
> 	void main() {
> 		auto obj = MyStruct();
> 		with(obj)
> 			writeln(helloworld());
> 	}
>
> Fails to run with the following error:
>
> 	$ rdmd test.d
> 	test.d(14): Error: undefined identifier helloworld
> 	Failed: ["dmd", "-v", "-o-", "test.d", "-I."]
>
> Even though `helloworld` should be "defined", by way of the `opDispatch` template.
>
> This also occurs when looking up identifiers in methods, when not prefixing the identifiers with `this`:
>
> 	import std.typecons;
> 	import std.stdio;
>
> 	struct MyStruct {
> 		auto opDispatch(string name)() {
> 			return name~"!";
> 		}
>
> 		void run() {
> 			writeln(helloworld()); // Error: no identifier `helloworld`
> 		}
> 	}
>
> 	void main() {
> 		auto obj = MyStruct();
> 		obj.run();
> 	}
>
> I can work around it via introducing a wrapper struct that contains the wrapped struct and uses `alias this` on it, which fixes the identifier resolution with methods, but not with `with`:
>
> 	import std.typecons;
> 	import std.stdio;
>
> 	struct MyStruct {
> 		auto opDispatch(string name)() {
> 			return name~"!";
> 		}
> 	}
>
> 	struct MyStructWrapper {
> 		MyStruct __mystruct;
> 		alias __mystruct this;
>
> 		void run() {
> 			writeln(helloworld()); // Prints "helloworld!"
> 		}
> 	}
>
> 	void main() {
> 		auto obj = MyStructWrapper();
> 		obj.run();
> 		with(obj) writeln(helloworld()); // Still fails
> 	}
>
> My use case for this is a D implementation of Mustache that compiles templates at compile-time, and can be used with arbitrary objects. The structure maintains the context stack (stored as a tuple), with `opDispatch` forwarding accesses to the first object in the stack that contains the named identifier. The tag content would be retrieved like `with(context) return mixin(tag_content);`, so that `{{helloworld}}` would generate `with(context) return helloworld;`.

This is probably an oversight as nobody's thought to use opDispatch and with in that manner. I don't know what the consensus will be on if it's a bug or not, but you can file an issue at issues.slang.org
February 05, 2015
On Thursday, 5 February 2015 at 20:45:36 UTC, Meta wrote:
> On Thursday, 5 February 2015 at 16:27:01 UTC, Alex Parrill wrote:
>> DMD does not seem to consider `opDispatch` when looking up variables in a `with` block, or . Is this intentional, or a bug/oversight?
>>
>> For example:
>>
>> 	import std.typecons;
>> 	import std.stdio;
>>
>> 	struct MyStruct {
>> 		auto opDispatch(string name)() {
>> 			return name~"!";
>> 		}
>> 	}
>>
>> 	void main() {
>> 		auto obj = MyStruct();
>> 		with(obj)
>> 			writeln(helloworld());
>> 	}
>>
>> Fails to run with the following error:
>>
>> 	$ rdmd test.d
>> 	test.d(14): Error: undefined identifier helloworld
>> 	Failed: ["dmd", "-v", "-o-", "test.d", "-I."]
>>
>> Even though `helloworld` should be "defined", by way of the `opDispatch` template.
>>
>> This also occurs when looking up identifiers in methods, when not prefixing the identifiers with `this`:
>>
>> 	import std.typecons;
>> 	import std.stdio;
>>
>> 	struct MyStruct {
>> 		auto opDispatch(string name)() {
>> 			return name~"!";
>> 		}
>>
>> 		void run() {
>> 			writeln(helloworld()); // Error: no identifier `helloworld`
>> 		}
>> 	}
>>
>> 	void main() {
>> 		auto obj = MyStruct();
>> 		obj.run();
>> 	}
>>
>> I can work around it via introducing a wrapper struct that contains the wrapped struct and uses `alias this` on it, which fixes the identifier resolution with methods, but not with `with`:
>>
>> 	import std.typecons;
>> 	import std.stdio;
>>
>> 	struct MyStruct {
>> 		auto opDispatch(string name)() {
>> 			return name~"!";
>> 		}
>> 	}
>>
>> 	struct MyStructWrapper {
>> 		MyStruct __mystruct;
>> 		alias __mystruct this;
>>
>> 		void run() {
>> 			writeln(helloworld()); // Prints "helloworld!"
>> 		}
>> 	}
>>
>> 	void main() {
>> 		auto obj = MyStructWrapper();
>> 		obj.run();
>> 		with(obj) writeln(helloworld()); // Still fails
>> 	}
>>
>> My use case for this is a D implementation of Mustache that compiles templates at compile-time, and can be used with arbitrary objects. The structure maintains the context stack (stored as a tuple), with `opDispatch` forwarding accesses to the first object in the stack that contains the named identifier. The tag content would be retrieved like `with(context) return mixin(tag_content);`, so that `{{helloworld}}` would generate `with(context) return helloworld;`.
>
> This is probably an oversight as nobody's thought to use opDispatch and with in that manner. I don't know what the consensus will be on if it's a bug or not, but you can file an issue at issues.slang.org

That should be issues.dlang.org. I hate smartphones and their autocorrect...
February 06, 2015
On Thursday, 5 February 2015 at 20:45:36 UTC, Meta wrote:
>
> This is probably an oversight as nobody's thought to use opDispatch and with in that manner. I don't know what the consensus will be on if it's a bug or not, but you can file an issue at issues.slang.org

Looks like two issues have already been opened: https://issues.dlang.org/show_bug.cgi?id=6400 and https://issues.dlang.org/show_bug.cgi?id=9808. Looks like neither have any discussion or resolution, which is a bit disheartening. I'll see if I can bump the latest one.