www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - with statement not triggering opDispatch?

reply "Alex Parrill" <initrd.gz gmail.com> writes:
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;`.
Feb 05 2015
parent reply "Meta" <jared771 gmail.com> writes:
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
Feb 05 2015
next sibling parent "Meta" <jared771 gmail.com> writes:
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...
Feb 05 2015
prev sibling parent "Alex Parrill" <initrd.gz gmail.com> writes:
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.
Feb 05 2015