Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upWishlist: functions with keyword args, optional args, and/or variable-arity argument (varargs) lists #323
Comments
This was referenced Sep 25, 2014
pnkfelix
added
the
postponed
label
Sep 25, 2014
This comment has been minimized.
This comment has been minimized.
flying-sheep
commented
Oct 8, 2014
depends on how you see it. the API will definitely be well-considered given the constraints of no default/kw arguments. but once those are added, i’m sure the API will be considered lacking, especially in areas where new defaults render old functions obsolete. a good example (if the new syntax sugar wouldn’t exist) would be fn slice(&self, start: uint, end: uint) -> &'a [T];
fn slice_from(&self, start: uint) -> &'a [T];
fn slice_to(&self, end: uint) -> &'a [T];
|
This comment has been minimized.
This comment has been minimized.
|
@flying-sheep so then you deprecate such methods, just like today, no? |
This comment has been minimized.
This comment has been minimized.
reem
commented
Oct 9, 2014
|
@pnkfelix I think his argument is that we don't want to be stuck with a ton of deprecated cruft in the stdlib, but I'm still personally not too sympathetic to the need to have default arguments before 1.0. |
This comment has been minimized.
This comment has been minimized.
flying-sheep
commented
Oct 9, 2014
|
yeah, that’s my argument. either cruft, or lengthy deprecation formalities and rust 2.0 a year after 1.0 (semver requires a major version bump for breaking changes) |
This comment has been minimized.
This comment has been minimized.
Valloric
commented
Oct 10, 2014
|
While I'd prefer to have optional/keyword args before 1.0, I believe the problem with deprecated functions crufting up the API can be substantially lessened by removing such functions from the generated API docs. This is how the Qt project (and D AFAIK) handles API deprecation; the deprecated stuff continues working but developers writing new code don't see it. Of course, the generated docs should have a setting/link/button to show the deprecated API items but it should be off by default. I think this is also a good idea in general; just a couple of days ago I accidentally used a deprecated function because it seemed like a good pick and I didn't notice the stability color. |
This comment has been minimized.
This comment has been minimized.
|
Rustdoc's handling of deprecated items definitely needs some improvement - see rust-lang/rust#15468 for some discussion. |
This comment has been minimized.
This comment has been minimized.
|
See the "Struct sugar" RFC for another take. |
pnkfelix
changed the title
Wishlist: functions with keyword args, optional args, and/or variable-arity argument lists
Wishlist: functions with keyword args, optional args, and/or variable-arity argument (varargs) lists
Mar 11, 2015
This comment has been minimized.
This comment has been minimized.
gsingh93
commented
May 18, 2015
|
I'd like to see some of these RFCs revived in the near future, if someone has time to do so. |
This comment has been minimized.
This comment has been minimized.
aldanor
commented
May 23, 2015
|
Agreed, there's a whole bunch of different keyword arguments proposals floating around and there's been a few discussions which seemed to die off a few months ago... would love to hear the current standpoint on this. |
matthewkmayer
referenced this issue
Nov 3, 2015
Closed
SQS: expose ReceiveMessageRequest or new convenience function? #105
This comment has been minimized.
This comment has been minimized.
e-oz
commented
Dec 4, 2015
|
Ok, 1.0 released, even more, can we please discuss it again? especially default arguments. |
This comment has been minimized.
This comment has been minimized.
|
This issue is open, it's free to discuss. |
This comment has been minimized.
This comment has been minimized.
(though its possible an https://internals.rust-lang.org post might be a better UI for undirected discussion ... we didn't have the discuss forums when we set up these postponed issues...) |
This comment has been minimized.
This comment has been minimized.
yberreby
commented
Dec 10, 2015
|
I'd love to see keyword arguments. I opened a thread on /r/rust with some comments about them before finding this issue. I guess /r/rust is an appropriate place for "undirected discussion" too? |
This comment has been minimized.
This comment has been minimized.
|
In any case, this should be done in such a manner that it does not cause very inconsistent libraries, perhaps by letting the named parameters be optional? For example the names could be given by the argument name. Such that, the function: fn func(a: u8, b: u8) -> u8;can be called both with and without named parameters, for example: func(a: 2, b: 3)or something along this, while still being able to do: func(2, 3) |
This comment has been minimized.
This comment has been minimized.
|
Also, this feature could easily be misused by taking named parameters instead of structs, which, I think, is a bad thing. |
This comment has been minimized.
This comment has been minimized.
golddranks
commented
Dec 10, 2015
|
I think it's because supposedly people are thinking about some kind of heterogenous variadicity (like the case of println, which is currently done with macros), and that isn't possible with arrays. |
This comment has been minimized.
This comment has been minimized.
|
I see, but that's why we got macros. If you want heterogenous variadicity, you gotta go with macros, after all the Rust macro system is very powerful. |
This comment has been minimized.
This comment has been minimized.
yberreby
commented
Dec 10, 2015
|
I agree, macros are appropriate for this. |
This comment has been minimized.
This comment has been minimized.
reddraggone9
commented
May 24, 2018
•
|
Multiple variations of opt-in named args have been mentioned both in this thread and in a related internals discussion linked above. In fact, it looks like making them opt-in was the plan. I would recommend that anyone thinking about contributing here read both threads. Otherwise we'll just keep retreading old arguments, which doesn't add much to the discussion. |
This comment has been minimized.
This comment has been minimized.
|
@varkor yes the IDE argument is very flexible and applicable in multiple directions. You could e.g. argue that a) you can configure it to display names whenever you want for your use case... I call this IDE induced foveation |
This comment has been minimized.
This comment has been minimized.
bbatha
commented
May 25, 2018
This is also true of the builder pattern. Though I do share your concern about forgetting to specify an optional argument. Perhaps rust should have a syntax like
Rust already has two ways to approach this pattern
The builder pattern feels odd and clunky if you come from a background of languages with named parameters. Even if you've seen it before the Rust builder pattern has nuances that don't exist in other languages which hurt its learnability: e.g. which flavor of |
This comment has been minimized.
This comment has been minimized.
bombless
commented
May 28, 2018
|
One way to avoid the chaos named arguments can bring is to only allow named arguments appear on private functions (that is, functions that are not marked as |
This comment has been minimized.
This comment has been minimized.
vvuk
commented
May 28, 2018
|
Another possible option would be to both introduce language syntax for
named arguments to distinguish them from positional ones (@name?) *and
require* that the names be used at call sites.
|
This comment has been minimized.
This comment has been minimized.
That doesn't solve my complaint with non-opt-in named arguments: that it changes improving a name from a local question (since it can only affect the current function) to a module-level question. That's annoying for both humans and IDEs, and as a result discourages improving names. |
This comment has been minimized.
This comment has been minimized.
leodasvacas
commented
Jun 8, 2018
@est31 Thanks for listing out your concerns. This one is in a way crucial to optional args, since they're all about adding args without breaking existing code. But I agree that knowing whether an argument list is or is not exhaustive can be useful information when modifying code. What would you think of a syntax |
This comment has been minimized.
This comment has been minimized.
sighoya
commented
Jun 8, 2018
Or they hide the fact that you can pass fewer arguments at the function call side. I don't know why there is so much hate about optional args and named arguments, they are both syntactic sugar which is resolved by the compiler. I don't know why this should be a breaking change since functions with default arguments are normal functions with the same arity as before but with the option to omit some arguments at the call side in favor to default settings suggested by the library/function creator. The omitted arguments are then filled up by the compiler. Whereas named arguments don't change the arity of the function only the struct in which all named args are packed in. Named arguments are better than normal struct parameters in that they allow default values which don't have to be defined in a struct outside the function and which can be easily overdefined without to create a second default struct where only one value of 40 values has changed. And no, keyword arguments are also type checked. Optional and named arguments will significantly reduce the misuse of traits in order to achieve variability or optionality. Variadic arguments are more powerful than arrays in that they can allow for heterogeneous types. Further variadics are some form of generics which allow to parametrize over function signatures. |
This comment has been minimized.
This comment has been minimized.
|
@leodasvacas yeah |
This comment has been minimized.
This comment has been minimized.
|
@leodasvacas adding to that: there is surely a tradeoff here of features. I don't think that there is a positive sum game result here, sadly :/. Another point:
Hard to check:
Even harder to check (you'd have to check the signature of the function to find out the default for emit_event_when_open):
The last example can be fixed by a lint that checks whether you set a named optional arg to the default. |
This comment has been minimized.
This comment has been minimized.
leodasvacas
commented
Jun 8, 2018
•
|
@est31 I'm sure rustfmt would be able to order your named arguments alphabetically. Edit: Also we could require that arguments are used in the same order that they are declared, like Swift does. Python doesn't require this. |
This comment has been minimized.
This comment has been minimized.
bbatha
commented
Jun 8, 2018
•
If you put the args in a hashmap that's O(n). If you sort them its O(nlogn), for a small amount of arguments, or for the "visual implementation" of the sorting algorithm is sufficient, and is easily assisted by rustfmt as @leodasvacas notes. |
This comment has been minimized.
This comment has been minimized.
pirate
commented
Jun 8, 2018
•
|
If omission is allowed but not reordering, you could always just do an def: system.open_valve(id, opening_speed=1.00, emit_event_when_open=false, send_drone=true, other_val=1.00)
ex1: system.open_valve(id, __________________, emit_event_when_open=false, send_drone=true, other_val=1.00)
ex2: system.open_valve(id, opening_speed=1.00, emit_event_when_open=false, send_drone=true, ______________) |
This comment has been minimized.
This comment has been minimized.
|
Lol when I mentioned landau O I've originally meant how long it takes for me to compare the lists manually. But yeah if they are sorted such a comparison can be done in |
This comment has been minimized.
This comment has been minimized.
pirate
commented
Jun 8, 2018
|
This is not really ever an issue in other languages that have keyword args though, e.g. Python. |
This comment has been minimized.
This comment has been minimized.
bbatha
commented
Jun 8, 2018
•
I'd like to point out that this is also a problem in structs where there is no implied ordering of fields, and with the |
This comment has been minimized.
This comment has been minimized.
jgarvin
commented
Jul 14, 2018
•
|
|
DJMcNab
referenced this issue
Aug 29, 2018
Open
Parameter Hints shown inline all the time (like IntelliJ) #16221
This comment has been minimized.
This comment has been minimized.
csharad
commented
Aug 30, 2018
|
Since we are brainstorming, I would like to pitch in my thoughts on this. The syntax inspiration is from Dart as well as Swift. The arguments can be both positional and named & it is backwards compatible. fn function(a: bool, { b: i32 });
=> function(false, b: 54);
fn function({ a: bool, b: i32 });
=> function(a: false, b: 54);
/// Not allowed.
fn function({ a: bool }, b: i32);
/// Current syntax still works
fn function(a: bool, b: i32);
=> function(false, 32);
/// Swift like external names for named arguments
fn start({ from start_loc: u32, to end_loc: u32 });
=> start(from: 4, to: 10);With Default Arguments fn function({ a: bool = false, b: i32 = 4 });
=> function();
=> function(a: true);
=> function(b: 6);
fn function(a: bool = false);
=> function();
=> function(true);
/// All allowed syntax
fn function({ a: bool, b: i32 = 4 });
fn function({ a: bool = false, b: i32 });
fn function(a: bool = false, b: i32 = 4);
fn function(a: bool, b: i32 = 4);
fn function(b: i32, a: bool = false);
fn function(a: bool, b: i32 = 4, { c: bool });
=> function(true, 5, c: false);
=> function(true, c: false);
fn function(a: bool, b: i32 = 4, { c: bool = true });The order of the argument names:
|
nagisa
referenced this issue
Sep 1, 2018
Closed
Is it idiomatic to use `impl<T> From<T> for Option<T>` in argument position? #53886
This comment has been minimized.
This comment has been minimized.
Kroc
commented
Oct 4, 2018
|
Wow, I'm a total minority here; I'm actually against this because it involves going to the documentation more often because a function is more "magic" than before. When you stare at a piece of code and you can't tell what it's doing because the function name is very short, but the parameters don't tell you what is happening (a good reason for parameter names, but not optional params). Optional params bloat such functions with leader code that has to deal with the optional elements, when really this "optional" stuff can be handled in alternate functions that do the preparation, and then call the canonical function. In every language that has optionals that I've coded in, optionals have not made my code easier to maintain, optimise, or even read. In practice it adds bloat to every such function and reduces readability at the call site. It makes API changes harder because now you have many call sites that have different semantics based on arrity, rather than name. This is no good for search and replace let alone refactoring tools. Nothing good will come with optionals, but param names and varags should not be conflated as the same beast, these do have purposes and it should be seen that it's OK to reject optionals, but implement param names / varargs. |
This comment has been minimized.
This comment has been minimized.
crumblingstatue
commented
Oct 4, 2018
•
Sure, it can be abused, like most language features, but that doesn't mean it doesn't have valid use cases. Consider the constructor of
It is pretty clear that this creates a Now let's consider the alternatives in Rust. 1. Explicit argumentsDo nothing fancy, just require all arguments to be explicit.
This definitely has the advantage of being explicit about everything, so there can be no misunderstandings. However, the extra explicit arguments given are all defaults. If they weren't explicitly provided, it would be very sensible to assume that the function uses the defaults. What's the disadvantage? Well, simply put, it's annoying for the user to always have to explicitly provide defaults. If there are a lot of functions like this, it can wear the user down, and make them annoyed with the API. "Why do I always have to say (..., Foo::default(), Bar::default(), ...)? All I want is a window of this size and this title. This is annoying." Although I do acknowledge, that a "serious" systems programming language might not want to prioritize convenience over explicitness. But Rust can be, and is used for developing applications, games, etc.. If we want to compete with all areas of C++, we might want to consider the convenience features that C++ provides. 2. Different functions for implicit/explicit args
Now we have two functions that essentially do the same thing, only one provides sensible defaults, the other is explicit. This has no advantage over defaulted params. 3. Builder patternThis is the most commonly used "substitute" for optional args. The usage would look like this:
The advantage here is that it's explicit that this is a "builder", so it has optional args. No "surprise" optional args. However, it has several disadvantages. The biggest one is API inflation. Now you have to have a It also makes the default case uglier. Now instead of just simply calling a function, the user has to create a builder, and call This would also look very ugly and unintuitive for functions that aren't constructors. Consider The default usage is What would this look like with builders? 4. Fancy magic with Rust genericsYou can do fancy things with Rust traits. For example, you could implement The API becomes harder to understand due to all the different generic types involved. The user can't look up the usage in one single place. They have to look for what implements Compile times can potentially suffer, but probably not by much. And finally, generic methods can't be called on trait objects, so this solution can't work in any context where dynamic dispatch is required. Addressing the rest of the arguments
This isn't a problem if it's kept simple, like with SFML in the above examples.
In the above examples, the alternate APIs had more "bloat" than an API with language-level optional args would. Again, readability is not a problem if the provided defaults are sensible.
This is also true for many uses of macros and generics, which Rust supports in spite of this. |
This comment has been minimized.
This comment has been minimized.
Ichoran
commented
Oct 5, 2018
|
I would like to see default arguments have the same level of support as default copying of structs. After all, an argument list is isomorphic to a struct containing all the arguments. The one wrinkle is that you only want to give a
This doesn't suggest an obvious way to provide the defaults, however. The closest analog to an It also doesn't address whether default arguments should be constants or whether they can be computed from the non-default arguments. Constants are less surprising, but computed defaults can be extremely useful in cases where you would other have to use ad-hoc sentinel values (e.g. if the default should be to match the length of an input). |
This comment has been minimized.
This comment has been minimized.
|
I've proposed structural records (#2584), it's not exactly named function arguments (so I'm keeping this issue open), but it overlaps a bit... |
This comment has been minimized.
This comment has been minimized.
crumblingstatue
commented
Nov 2, 2018
Keep in mind that this issue is not just about named args, but also about optional args. |
This comment has been minimized.
This comment has been minimized.
And "variable-arity functions" which probably includes the huge topic of variadic generics. Considering this and the number of comments here, I wonder if this issue should be split into multiple ones. |
This comment has been minimized.
This comment has been minimized.
crumblingstatue
commented
Nov 4, 2018
•
|
For those interested in these features, check out #1806 (comment)! Using #2584 in conjunction with #1806 could provide a solution that I believe would cover most of the use cases for named/default args. |
pnkfelix commentedSep 25, 2014
A portion of the community (and of the core team) sees one or more of the following features as important for programmer ergonomics:
This issue is recording that we want to investigate designs for this, but not immediately. The main backwards compatibility concern is about premature commitment to library API's that would be simplified if one adds one or more of the above features. Nonetheless, We believe we can produce a reasonable 1.0 version of Rust without support for this.
(This issue is also going to collect links to all of the useful RFC PR's and/or Rust issues that contain community discussion of these features.)