-
Notifications
You must be signed in to change notification settings - Fork 1.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
Syntax sugar for prefix-style type parameter lists. #122
Conversation
This is a proposal for type parameter lists that come well before the actual generic items. Example: ```rust type <T: Unwieldy+Traits+Go+Here, U: Even+More+Traits> { fn foo(t: T) -> U { ... } fn bar(u: U) -> T { ... } } ```
I agree this is definitely an issue. I'm not sure if this is the right solution but it is definitely something we should think about. I think @nikomatsakis has a proposal in the works for |
I still like the syntax I proposed in http://blog.octayn.net/blog/2014/02/01/parametric-polymorphism-declaration-syntax-in-rust/ |
The block behavior that allows to define several values parametrized on the same parameters (which are then implicitly added as extra parameters to the values, instead of requiring a specific accessor syntax as you would in a struct/module) can be convenient; besides C++ templates, it is also the mechanism behind Section in Coq. That said, the "long unwieldly list of constraints/traits" part would be better solved by simply a constraint definition/aliasing mechanism, as GHC constraint synonyms. Let's call that a "trait synonym". In your example type <L:LatticeDir + Combine,
T:Clone + InferStr + LatticeValue,
V:Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>>
pub fn lattice_vars(this: &L,
a_vid: V,
b_vid: V,
lattice_dir_op: LatticeDirOp<T>)
-> cres<LatticeVarResult<V,T>> {
[...]
} what I actually want to write is a definition of the type-level information that makes a lattice: trait Lattice<L, T, V> = <
L: LatticeDir + Combine,
T: Clone + InferStr + LatticeValue
V: Clone + Eq + ToStr + Vid + UnifyVid<Bounds<T>>
>
pub fn lattice_vars<(L, T, V): Lattice>
(this: &L,
a_vid: V,
b_vid: V,
lattice_dir_op: LatticeDirOp<T>)
-> cres<LatticeVarResult<V,T>> {
[...]
} It does not only avoid redundancy: by introducing a name, it also increases readability. (Interestingly, PS: one issue with trait synonyms is that it often make sense to give constraints on the same type variable in different place. In this example you may well consider that |
"Unwieldy+Traits+Go+Here" ... I have become torn between C++ and Rust a little on this sort of thing; I miss the ability to write generic/overloaded functions without having to specify trait-bounds, and I'm a bit worried what it will all look like once there's the ability to overload on multiple parameters and you have to start specifying complex relationships between types. I like the ability to just focus on functions. Perhaps it would be nice if they were optional (which is what we'll get in C++ once it finally gets concepts) - write code,make it work.. and add bounds wherever they solve more problems than they cause. IMO the real problem in C++ is header files, where you had to have included the right headers to declare the overloads.. and Rust wouldn't suffer from that problem There's even a nice proposal for C++ that would make 'auto' sugar for type-params in function argument lists. Rusts' syntax could be even cleaner. |
I like the proposal and was going to propose something similar.
Even in our current
I would rather do a more direct, mechanical translation, for greater simplicity and predictability: Items within a |
A comment on how the interaction of "trait synonyms" and the where-clauses RFC #135 : there is a design space regarding how to abbreviate constraints, and the syntax I suggested is only one (and certainly not the best) possible proposal. But in any case, where-clauses would be a very nice thing to improve the use of trait/constraint synonyms. In the current syntax there is no separation between the place to introduce a parameter, and the place to constrain it with a trait bound. The syntax I suggested above
allows to give a name to a sequence of binders (that introduce new parameters in scope), because there is currently no other way. But as noted this is awkward, as you may want to give a name to some aspects of the bounds If RFC #135 is accepted and where clauses become available, you can drop the idea of giving a name to a binding site, and only give a name to the corresponding constraint. You would then write:
where The Haskell language historically had an evolution that is reminiscent of the move from traits to a general notion of constraints. At the beginning, the only form of qualified types where type-classes ( |
I just noticed an analogy: I think this is the same thing that happens for the type parameters introduced by a |
Thanks for submitting an RFC! We discussed this at the triage meeting today, and the consensus was to simultaneously close this as postponed an in favor of #135. Where clauses provide much of the same syntactical benefit of grouping together type parameters, and we'd otherwise like to postpone the grouping of type parameters for multiple function scope. Closing for now. |
This is a proposal for type parameter lists that come well before the
actual generic items. Example: