-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
RFC: variadic generics #10124
Comments
Have you tried implementing the same use cases using macros? If so, how well did it work? |
Well, I'm not sure if any of this can be implemented with macros. You can emulate some variadic functions with macros (by writing them as macros in the first place), but it's nowhere near automatic. |
My feeling: I think we will eventually want something like this if we aim to have trait types subsume closure types, but not for 1.0. I liked the idea of leveraging tuples but I don't know if complications arise and so forth. |
@nikomatsakis afaik @eddyb is actively working on impleementing this |
(also, 👍 on the proposal) |
I've done some research for the first part, expanding |
@catamorphism The issue with macros is: a. they cannot be used in methods, b. they are brittle and don't give very good error messages, and c. they have no knowledge of the type system. The nice thing about variadic generics is also that it will allow us to desugar lots of the language. @eddyb Have you looked at D's variadic type params? |
@eddyb: maybe another implementation to look at would be clay, though they have a quite a bit more powerful generics system than Rust. |
@bjz I have now, it uses tuples as well, but I'm not seeing tuple destructuring (e.g. @Blei oh, Clay has pretty much the same concept, AFAICT. Thanks for that, better to reinvent the wheel in a way that works (and we like prior work in Rust, don't we?). |
@eddyb Why not T.. ? (A,B,C).. => A,B,C fn call(self, args: Args..) -> Ret { |
@liigo prefix That being said, I'm not fundamentally opposed to a postfix |
My only concern here is whether/how this might interact with type inference, and future things like higher-kinded types (or i.o.w. just the presence of a kind level above the type level at all), type-level currying if we ever add it (see "Type system thoughts" email for why we might want to), and so forth. In particular, if we have kinds, would And, there's some of this in the OP, but could you do a compare-and-contrast (of advantages/disadvantages, expressiveness, simplicity/complexity etc.) relative to C++'s variadic templates? Variadic templates are super useful, but they're also super far away from anything that could be called simple and elegant. |
I'll admit to some trepidation about potential interactions with other parts of the type system as well. I don't know what problems might arise because I haven't given this any serious thought, and I don't think I will have time to give this serious thought until the rest of the system is more nailed down. |
I read over the proposal in more detail and I've got some thoughts and questions. First off, I think we may want to model this in the Rust model that I've been working on. This is, after all, what it's for -- to uncover complications that arise before we are knee deep in implementation. Unfortunately the model is currently limited to the reduction semantics (no type system yet). Second, here is an attempt to codify the rules that I see in what you wrote. Let me know if you think this is accurate:
I think this largely holds together, but this is only a cursory examination. Mostly just trying to extract rules from the examples. I didn't think too hard about HKT, but my first thought is that a tuply type parameter just has kind Some questions / thoughts
But by the rules I gave above this an error, because
|
Ah, I see in your examples you permit a "tuply" type parameter to come first in the list as well. I think we'll need a rule like "at most one tuply type parameter on any given type" to prevent ambiguity. I could imagine this creating problems, though. Another option might be that we require users to provide tuple types for the values of tuply type parameters -- or maybe permit either In other words, given |
Thinking more about this, I see that my attempt at crafting rules was wrong. The type grammar is more like:
and so on. |
@eddyb wrote to me on IRC that I was misinterpreting the meaning of |
C++11 allows template parameter packs out of anything, including templates (higher kinds) and non-types, which in this case we wouldn't. The primary incentive to have them at all though is function parameter lists, which are simply-kinded, so maybe this is not a problem. |
cc |
@eddyb this proposal's got quite a feedback. All RFCs should now go through the new RFC process but it will take time to write all those RFCs. However, given the feedback on this proposal, it would be good to submit it in the rfc repo and start getting some feedback there as well. |
Just thought I'd 👍 this as I've come across a couple use-cases in the past two days where something like this would have been perfect. |
Should this be rewritten and go through the new RFC process? |
@sinistersnare: Yes, that's what needs to happen to it. It's not a backwards incompatibility risk so there's no point in leaving around an issue here. |
This issue has been moved to the RFCs repo: rust-lang/rfcs#376 |
The Problem
bind
method,f.bind(a, b)(c) == f(a, b, c)
) and defining such functions may only be done (in a limited fashion) with macrosThe Solution: Part One
C++11 sets a decent precedent, with its variadic templates, which can be used to define type-safe variadic functions, among other things.
I propose a similar syntax, a trailing
..T
in generic formal type parameters:The simple example above only uses
..T
, but notT
itself.The question which arises is this: what is
T
? C++11 has a special case for variadic parameter packs, but we can do better.We have tuples. We can use them to store the actual variadic generic type parameters:
The Solution: Part Two
Now that we know the answer is "tuples", everything else is about extending them.
The prefix
..
operator would expand a tuple type:Then we can do the same thing with values:
There's only one piece missing: we're still not able to define a function which takes a variable number of arguments.
For this, I propose
..x: T
(where T is a tuple type) in a pattern, which can be used to "capture" multiple arguments when used in fn formal arguments:A type bound for
..T
(i.e.impl<..T: Trait>
) could mean that the tupleT
has to satisfy the bound (or each type inT
, but that's generally less useful).Examples:
Todo
The text was updated successfully, but these errors were encountered: