COMMUNITY

@:autoGenericBuild

Why @:autoGenericBuild missing? I can already work around this with a simple trick, so it is unlikely that anything will break with the addition of the usual way to do it.

Because an actual use case for it is hard to conceive. What problem would you solve with this?

The same problem that @:autoBuild solves. This eliminates the need to manually write @:build metadata wherever it is needed. It’s just a matter of convenience.

For a concrete example, take a look at the msignal library at least. There are three classes Signal0, Signal1 and Signal2, created using copy-paste and changed for the required number of arguments. Macro @:genericBuild can turn this into one class GenericSignal that takes one type parameter of the handler. In this case, with one type parameter, we can set not only any required number of arguments and their types, but also set the sane names of the arguments, and not value1, value1 … value42.

And if you look at GenericSignal, then it in its essence turns into an event dispatcher template. We may want to have several of these templates, and then @:autoGenericBuild comes in handy to save us the trouble of writing @:genericBuild with a long path to our build macro as an argument in each dispatcher class.

This is the part where I don’t follow. Could you please illustrate that, because I can’t figure out how that’s supposed to come together. You can have two build macros run on a single type (be it via @:autoBuild or directly), because both modify that type (which may or may not cause problems, but it’s possible). You cannot have two @:genericBuild macros run on the same type, because a generic build macro produces a different type altogether.

I mean, as I understand it, you want this:

@:autoGenericBuild(Foo.bar()) interface I {}
@:autoGenericBuild(Beep.bop()) interface J {}
class A implements I implements J {}

Which is supposed to behave like so?

@:genericBuild(Foo.bar())
@:genericBuild(Beep.bop())
class A {}

This will run Foo.bar() and then that’s it (I’m not sure what else it could do, except erroring on duplicate @:genericBuild). I presume this is not what you want. So, would you mind showing an example of what you would like to work?

No, something like this:

@:autoGenericBuild(DispatcherBuilder.build())
interface IDispatcherTemplate {}

class Callback<THandler:Function> implements IDispatcherTemplate {
	function dispatch() {
		// the algorithm does not depend on the signature of the handler.
		// It relies on a macro to substitute the correct call.
	}
}

class Promise<THandler:Function> implements IDispatcherTemplate {
	function dispatch() {
		// dispatching algorithms can be different
	}
}

class EventDispatcher<THandler:Function> implements IDispatcherTemplate {
	function dispatch() {
		// but the substitution method for calling the handler is the same for all
	}
}

Ok, I see. Hmm. I guess this has never really come up. One reason might be that the resulting compile time cost shows in larger code bases. Every time you write EventDispatcher<String->Void> the @:genericBuild macro has to run to resolve it (to the very same type). So while you can indeed use @:genericBuild to avoid copy pasting code between Signal0, Signal1, Signal2, you’d probably still want to define them as typedefs at least.

But yeah, I don’t think there’s anything prohibitive about this, so it’s probably best to request it via a GitHub issue.