A more explicit API?
clipperhouse opened this issue · 8 comments
The current gen API is designed to get you going with a minimum of effort. Simply by adding a // +gen
directive above your type, you get a whole bunch of Linq-y (underscore-y) methods right out of the box.
While that’s a nice demo and first experience, I am thinking it’s not ideal.
First, it creates a bunch of methods you may never use, which is bloat.
Second, it’s not very Go-ish. I think we value explicitness over magic. You can subset them, // +gen methods:"Any,Count,Where"
, but…
If you also want projection methods, you use a special tag, indicating types, eg projections:"int,Foo"
. This tag then looks at the methods you’ve specified (or not) and basically multiplies the types and the methods.
Combinatorially, it can be a lot. Explaining (and implementing) the interaction of methods × types is messy.
I propose that all methods should be explicit (no magic) and combined into a single tag. It would look something like:
// +gen slice:"Count,Where,GroupBy<Foo>,SortBy<int>"
This is a breaking change, but perhaps better for the long term. Thoughts?
I like the direction. Maybe leave an explicit // +gen automethods
or something in case you want the magic experience still.
Would it be possible to detect what methods are being used automatically and generate them on-the-fly as needed? This might require walking the AST, or something else equally insane, but it seems possible.
+1 for that. I might try to make a PR for some things along those lines if Matt doesn't beat me to it. It would increase usability a lot.
If this is possible you could completely dispense with anything other than adding a bare // +gen
comment. Everything else is inferred automatically. You could probably even infer projection for methods like myThings.SelectString(...)
, but that might be pushing it a bit.
In any case, I'll be watching closely.
I think the // +gen still gives you a starting point so you're not blindly searching for things to generate, although it might not be much farther of a stretch.
Interesting idea. So the idea is, go ahead and use the non-yet-generated methods, have gen detect them and then write the implementation. Slick indeed.
We’d have to walk the AST, identify the method based on receiver as a candidate. The name would have to be recognized as mapping back to a method name that would be generated. This is the semi-deterministic part. I suppose we’d have to ‘ask’ the typewriters – hey, do you recognize this name?
(Keeping in mind, the program is invalid at this stage, where the method is called but doesn’t exist. Syntactically parseable but not buildable.)
I’d say it’s a longshot at the moment but happy to see attempts.
@wfreeman actually... how hard would it be to test all types that match the pattern type Xs []X
? Surely this pattern doesn't happen very often unless you want to do gen-like operations on them (notably, sorting). If you remove the need for all annotations, the barrier to entry drops really far. You no longer have to think ahead, all you need is a type that is a slice of something and boom you can use all these methods.
go ahead and use the non-yet-generated methods, have gen detect them and then write the implementation
Exactly. The only thing that would make it better is if you could hook into go build
to make the whole thing seamless. Alas, it doesn't look like that will happen anytime soon.
This shipped in https://github.com/clipperhouse/gen/releases/tag/v4.0.0