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

Reply via email to