-
Notifications
You must be signed in to change notification settings - Fork 17.6k
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
proposal: Go 2: mini-package: a solution to unify Go builtin and custom generics #32895
Comments
For what it's worth, I don't understand exactly what the proposal means, nor how to implement it. |
I don't understand how to write the |
@rsc This proposal is very rough. There must be many flaws and logic problems in it. Hope it will inspire someone to get a better Go generic design idea. Basically, this proposal tries to decouple the generic parameter declaration part and the function/type implementation parts, so that main generic body code still keeps looking as Go 1 style and a better readability is got. (I really don't like the cumbersome feeling in the syntax designs of C++/Java/Rust, especially their generic designs.) I don't have an idea on how to implement it too (if even if you neither, ;D). Maybe it can be implemented in a 3rd-party code generation tool, but I think the experience will be smoother when implementing it as a builtin feature. @ianlancetaylor The
Use it:
|
@dotaheor Have you considered looking at code generation for this? See this: https://github.com/ncw/gotemplate |
@Fabian-F Your project is cool, but it looks it only works well for some data struct use cases. A general generic solution will support more variations. I ever had a similar idea by using type alias in a package as generic inputs. I planed to use |
@dotaheor it's not actually my project. I actually typed something similar to what you're describing but decided not to suggest it. Generics as you describe them would be too dramatic of a change for Go, and amounts to simple templating. |
This proposal is really some like C++ template. I don't want to defend C++ template design, but I think C++ template design is not all bad. In fact, many C++ template uses are very readable. The problem of C++ templates is just that it enables people write strange-looking and hard-to-read (and hard-to-debug) code. This proposal has a distinct characteristic from C++ template design: the exported function/type declaration code parts never entangle with any new added generic element parts. This effectively protects the readability of Go 1 code. I admit this proposal is some dramatically to change Go, but I think the fact that the newly introduced |
@dotaheor At the end of the day this proposal is still just code templating, which would be much better achieved with a pre-processor (//go:generate) than by modifying the compiler and language spec to effectively achieve the same thing. I would love generics as much as anyone but there's been no decent suggestions on how to achieve them without complicating Go significantly. This gen keyword proposal is no different. Perhaps a sensible suggestion would be for an all purpose code preprocessor, which would allow for domain-specific syntax to be added and reduce endless arguing over language changes. This would allow you to create templating using your syntax, generate and substitute typenames. |
@Fabian-F This proposal is just an idea. It is far to be practicable to be implemented as a formal Go syntax set yet. It is presented here is mainly for inspiration purpose. Personally, I just think this proposal idea is interesting and is easy to understand. It can be viewed as an attempt to standardize all kinds of code generators, in the familiar function declaration and call manner, to solve some common problems in Go for lacking of custom generics. |
There are a lot of different ideas here, and I think they need more explanation. How many new keywords does this add? What does In the generics design draft contracts serve two purposes: they describe acceptable type arguments and they define permitted operations. It's not really clear whether they serve the same roles in this proposal. |
There should be two new keywords for sure: For "builtin generic privilege", I mean this current proposal doesn't unify builtin generics and custom generics perfectly. Builtin generics still have some privileges which custom generics can't get. Please note that this proposal just tries to make the docs of builtin generics look consistent with custom generics. The current builtin generics implementation needn't to be changed.
We can view this as a sub/mini-package is exported as an import, so the result can be assigned to an import identifier, then we can use the import identifier as qualified prefix like the current non-generic imports. When a
Generally, the types of the arguments should not be different, which is indicated by the example operator Maybe the optional inputs and operator generics features mentioned in the proposal are not good ideas.
I think sometimes named contracts have better readabilities. I tried to list potential useful builtin contracts here: https://gist.github.com/dotaheor/a746923b46d2514ceef49cb47958fd71 (please ignore the
Yes, this proposal tries to serve the same roles. The difference from the draft is it combines the |
@ianlancetaylor In fact, the |
I forgot mentioning that the design in the last comment requires each BTW, I rewrote the examples in this CL (https://go-review.googlesource.com/c/go/+/187317) with the styles of the proposal in this issue. Some small changes are added to simplify some simple single output |
I added a rule in the end of the proposal to make the unification complete reluctantly. |
I realized that I still don't understand the |
The contracts are created implicitly for the BTW, this proposal doesn't exclude explicit contracts. In fact it also works well with explicit contracts, but the syntax would be some different. In this proposal, Contracts are also defined as
(Please note that the newest version of this proposal has discard the Using the contracts as the way described in the draft is also possible for this proposal, though in my honest opinion, sometimes the relationship between generic types might be very complex so that creating a single contract to describe the relationship is not always flexible. |
In fact, the
|
Implicitly created contracts are not contracts. The point of a contract is that it is an explicit declaration of what kinds of type arguments are permitted, and it is an explicit restriction on what kinds of operations are permitted for type parameters. If the contract is implicit, then it depends on the exact body of the function. A small change in the body of the function can implicitly change the contract, causing code far away that calls the function to fail to compile. It's OK for that kind of failure to occur due to an explicit contract change, in which case it's clear that something might fail. It's not OK for it to occur implicitly. See the discussion at https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md#type-contracts. |
I see. But sometimes, it is too tedious to define explicit contracts. |
From my perspective that is like saying that sometimes it is too tedious to define the types of your function arguments and results. There are dynamically typed languages, and there are good reasons for them to exist. But Go is a statically typed language. |
I think implicitly created ones can also be called contracts. The difference is they are more casual than the ones defined explicitly. Explicit contracts (or function prototypes) play a pivot role, or a fixed point, to constraint both downstreams (generic or function callers) and the upstream (the definition body). On the other hand, implicit contracts, which are extracted from the definition body, only constraint downstreams. The advantages of implicit casual contracts are flexible and almost possibility complete. One drawback of implicit casual contracts is that they are often less constrained than intended. The other drawback is the one @ianlancetaylor has mentioned above: the implicit contracts not very formal so that they can be modified casually and easily. The advantages of explicit formal contracts are great API stability and more user/caller friendly. One disadvantage of explicit contracts (at least for the current draft version) is possibility limited. Another disadvantage is a new set of syntax is needed and sometimes it is tedious to define a contract if the relations between generic types are complex. I would prefer explicit contracts if the mentioned disadvantages are gone. |
I just improved my old contract description syntax to get a better readability. The new syntax is here. The syntax set is not small, but maybe this is inevitable. Readability is more important than simplicity. |
The first time I read this proposal I didn't understand it very well and seemed pretty complicated. After reading the proposal again (the current revision) and understanding it properly, I think it is brilliant! The way the built-in types and user-defined generic types are unified is shockingly elegant. I have to confess that I haven't dug too deeply into the details, but this way of writing generics is pretty novel and seems to go in the right direction to achieve orthogonality and uniformity in the type system. It still requires further simplification and refinement, but I'd say this proposal deserves attention. Thanks for the work! |
Perhaps I misunderstand, but it seems to me that this new proposal is completely different from the old one. It should probably be in a new issue. One of the ways that I judge a generics proposal is by the number of new names that it introduces. Currently Go has relatively few names compared to many other programming languages: 25 keywords and 39 predeclared names. One of the most important goals for Go is that it be simple, and a relatively small number of names is one way to judge whether that is succeeding. This new proposal seems to introduce a large number of new names, and in my opinion that is a mark against it. You say "readability is more important than simplicity." I don't agree. While both are important, simplicity is more important, and moreover simplicity implies readability. |
The new experimental explicit contract syntax set design is a potential part of this whole generic design. And yes, it can be separated out as a solo contract design proposal. I will do this after several days by improving it more. The whole design (the |
Indeed. However, the fact that these property names are defined well in Go specification lowers the learning cost. I also can't make sure whether or not the overall effect by introducing these names is positive or not. I just think the new design is almost possibility complete as implicit contracts, and it makes the definitions of some constraints less ambiguous than implicit contracts. |
Thanks for the proposal. We're going to continue with our current design draft for generics, which is significantly different from this approach. If that design draft fails, perhaps we can revisit your ideas. You are of course welcome to try implementing this and see how it goes. It is not something that we are going to pursue. Therefore, this proposal is a likely decline. Leaving open for four weeks for final comments. -- for @golang/proposal-review |
OK. Is it ok for me to post (create a new issue for) the contract design part some days later? |
BTW, the intention of I posted the idea set here and some elsewhere was expecting to get feedback to improve it. Up to now, some surprisingly, no much effective feedback is got, except thinking it is too different. @bradfitz, @griesemer, @iant, It would be great you can post some different opinions (other than thinking the idea set is too different) here. I will address them to make some adjustments. |
I feel like I've written quite a few comments on this proposal. Try writing out some real examples, like the ones in the generics design draft, and see how they look. Try working out an implementation strategy. If you genuinely think that your approach is clearly better than the one in the generics design draft--not just different, but clearly better--then show some examples on golang-dev and ask people which they prefer. |
No, this is certainly never what I intended to express. I think this is surely a misunderstanding. I do think there are several good points in this proposal, otherwise I would not post it here. But it is hard to say it is clearly better. The proposal project has some examples: https://github.com/dotaheor/unify-Go-builtin-and-custom-generics/tree/master/examples. Just please note that the new contract design hasn't been used in those examples (I will modify the examples to include the new contract design in several days). What I forgot mentioning in my previous comments is, I have not any experiences to implement a syntax parser. So I very expected anybody who have such experiences to tell me if this proposal is possible to be implemented. Is there any problems and difficulties in implementing this proposal? In particular some fatal problems make the implementation impossible. This will save much time for who have interests in implementing it. BTW, if anyone else have interests in implementing this proposal. Just feel free to do it. It is very appreciated if someone can make this proposal a reality or verify that it has fatal problems to do so. |
I have experimented using For instance, when parsing This is just a simple example of some of the syntactic problems that might arise. It takes time to find them and often requires implementing the parser (or use a parser generator that can detect such problems). So, it is a bit much to ask somebody else to find such problems in your proposal - it pretty much requires somebody to try to implement this. It is hard to just see those problems, and even harder if there is not even a syntax spec. This is just a tiny example of some of the difficulties that arise with a language change as large as a generics proposal. There are many many more, and many are much harder to resolve. If you feel like there are significant advantages in your design over the current contracts draft, perhaps you can show those advantages using small examples side by side. That might make it easier to see the good points of this proposal that one might want to consider. Thanks. |
@griesemer Thanks for the derailed explanations. This is by bar the most well-judged comment. I really hope these explanations can be posted earlier, at least along with making the proposal review decision. From your explanations, I can get the following reasons why this proposal is likely declined.
About whether not a trailing comma should be allowed in a generic parameter/argument list, I think the answer is this should be consistent with the I understand that here the fact that I would discuss more if there are other predictable difficulties are found in this proposal. I think it is not a good idea for decline proposal with many ideas just for a single problem or difficulty. I understand your concerns, but I think keeping this issue open (neither declined nor accepted) is better. In fact, I didn't very intend to create this issue a formal proposal. I hope it can show some ideas for inspiration purpose. In fact, I have maintained this proposal for about three years, improving it from time to time. I really hope Go can own a clean distinct generic system. BTW, this proposal doesn't exist as a contract proposal. It corresponds to the generic function and type declarations part in the draft. It is just a try to decouple the generic parameter lists from general function and type declarations to remove the cumbersome feeling and to avoid some unnecessary code duplication. The new explicit contract design mentioned above corresponds to the contract declaration part in draft. Currently, any contract may be presented with a set of constraint expressions, so there is even not the I will create a new proposal for the new explicit contract design without the |
I want to make clear that the proposal was marked as "likely decline" for the reasons stated in #32895 (comment), not because of syntactic details with square brackets.
We use the issue tracker as a list of things that the project needs to do. It does not help us to keep an issue open indefinitely with no way to move it forward. You can pursue this project and show ideas and provide inspiration without having an issue in the issue tracker. |
From my experience, putting all kinds of idea related discussions in one place is good for a community, doing this will unite popularity. And for an individual, this will save much time. |
For discussions about generics, we already have https://github.com/golang/go/wiki/Go2GenericsFeedback. |
@dotaheor I second @ianlancetaylor comments above. I brought up the (small) problems using In some cases, people will jump in and help out with the investigation, but that is usually the case when the proposal is compelling enough that people decide to spend that time. |
There is almost not any discussions. How many people will check that page from time to time? @griesemer |
@dotaheor I appreciate your frustration. The fact that nobody else has provided substantial feedback may indicate a lack of interest for this proposal, or a lack of time and resources to engage with it. For us it is not compelling enough to engage with it in more detail than we already have - we can't possibly help you figure out all the fine points; we simply don't have the time for that. We have to take all this at face value and conclude that the proposal is not compelling enough at this point. If you feel strongly about your proposal, it would be great if you could show us how it is solving problems better than our current contracts proposal, ideally with small examples that shows the differences side by side. That is also what @ianlancetaylor suggested earlier. Thanks. |
The examples are here: https://github.com/dotaheor/unify-Go-builtin-and-custom-generics/tree/master/examples, I have mentioned them several times. |
Just be aware that the contracts used the examples have not been changed to the new design yet. |
I updated both the contract and
All examples are also updated. |
Again, please read what we wrote in #32895 (comment) . The reasons given there have nothing to do with any adjustments to the proposal. |
@griesemer said "it would be great if you could show us how it is solving problems better than our current contracts proposal, ideally with small examples that shows the differences side by side. That is also what @ianlancetaylor suggested earlier." You've shown us the examples, but that is the less important part of what he asked for. Show us how this proposal solves problems better than the current design draft. And ideally do it here rather than pointing us to lengthy separate documents. I also want to echo one of @griesemer 's points: we have limited time and resources. From my point of view we've put a lot of time into examining and commenting on this proposal. As the author of the proposal it is your job to persuade people that your approach is a good idea. It is not our job to help you improve your proposal. We already have a design draft that we've put years of work into. If you want to convince us to put a lot of time into your proposal, you need to show us why it is better. |
Hi, @ianlancetaylor, I think I have listed the good points in the document. The most obvious good point is the proposal makes the looking of custom generic and built-in generic consistent. Another also obvious good points of this proposal is it removes the cumbersome feeling of generic function and type declarations. The good points are listed at the beginning of the document. I re-list them here for convenience:
|
Do you mean I need to post some examples here? |
Thanks. What do you mean by "makes the looking of custom generic and built-in generic consistent"? I'm not sure I agree about the "cumbersome feeling." It seems like where the design draft uses type parameters you use a new keyword and a new notion of mini-packages. I don't see why either approach is less cumbersome. |
OK, maybe I misunderstood something. Anyway, this might the last comment I made in this thread. I just intended to present some ideas here and hope some of them may have a positive impact in Go generic design process. You don't need to review it. I'm sorry if the reviewing have spent you much time. Here, I just post a (draft-2) example by adopting this proposal for comparison.
Update: add the implementation part. |
Closing it doesn't delete any information. We only leave issues open when there's something actionable to do. For just brainstorming what generics might look like, another forum is probably best. Per the comment above (#32895 (comment)) saying this is a likely decline, we're going to close this, as it doesn't look like there's been a change in consensus. |
https://github.com/dotaheor/unify-Go-builtin-and-custom-generics/blob/master/README.md
The proposal introduces a
gen
code element concept which is much like our familiarfunc
element concept, which makes the proposal very easy to understand.The text was updated successfully, but these errors were encountered: