Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support MethodInitializer syntax? #70

Open
marler8997 opened this issue Jan 28, 2020 · 0 comments
Open

Support MethodInitializer syntax? #70

marler8997 opened this issue Jan 28, 2020 · 0 comments

Comments

@marler8997
Copy link

marler8997 commented Jan 28, 2020

In DMD I added an interesting way to initialize "make rules" in build.d (https://github.com/dlang/dmd/blob/master/src/build.d). here's an example:

alias backend = makeRule!((builder, rule) => builder
    .name("backend")
    .target(env["G"].buildPath("backend").objName)
    .sources(sources.backend)
    .msg("(DC) BACKEND_OBJ")
    .command([
        env["HOST_DMD_RUN"],
        "-c",
        "-of" ~ rule.target,
        "-betterC"]
        .chain(flags["DFLAGS"], rule.sources).array)
);

If reggae were to support the same syntax, the following:

alias app = executable!(
    ExeName("example"),
    Sources!(cast(string[])null, Files("../../example.d")),
    Flags("-g -debug"),
    ImportPaths(["../src_hresult",
        "../src_cstring",
        "../../out/DerelictUtil/source",
        "../src_coreclr",
        "../src_clr",
        "../src_clrbridge",
        "../../out/dlibs/src",
    ])
);

could become:

alias app = executable!(e => e
    .ExeName("example")
    .Sources(cast(string[])null, Files("../../example.d"))
    .Flags("-g -debug")
    .ImportPaths(["../src_hresult",
        "../src_cstring",
        "../../out/DerelictUtil/source",
        "../src_coreclr",
        "../src_clr",
        "../src_clrbridge",
        "../../out/dlibs/src",
    ])
);
``

The code to support the syntax is here:

/** Initializes an object using a chain of method calls */
struct MethodInitializer(T) if (is(T == class)) // currenly only works with classes
{
    private T obj;
    auto ref opDispatch(string name)(typeof(__traits(getMember, T, name)) arg)
    {
        mixin("obj." ~ name ~ " = arg;");
        return this;
    }
}
/** Create an object using a chain of method calls for each field. */
T methodInit(T, alias Func, Args...)(Args args) if (is(T == class)) // currently only works with classes
{
    auto initializer = MethodInitializer!T(new T());
    Func(initializer, initializer.obj, args);
    initializer.obj.finalize();
    return initializer.obj;
}

It turned out to be a nice syntax/mechanism for build.d. It almost emulates named parameter semantics. It allows

  • configuration in any order
  • cross-referencing data between fields
  • no need to modify surrounding lines to add/remove new configuration (don't have to worry about the comma , character to separate function arguments)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant