Skip to content

Commit 0026373

Browse files
committed
optional parameters
1 parent 40f0c43 commit 0026373

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

active/0000-optional-parameters.md

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
- Start Date: 2014-07-03
2+
- RFC PR #: (leave this empty)
3+
- Rust Issue #: (leave this empty)
4+
5+
# Summary
6+
7+
This RFC proposes to add optional parameters to Rust functions.
8+
9+
# Motivation
10+
11+
Currently in Rust there are a lot of functions that do the same thing, but take a different number of parameters.
12+
The current design forces those functions to have different names.
13+
This causes the standard library to have badly-named functions.
14+
15+
# Detailed design
16+
17+
Optional arguments are an implicit form of overloading.
18+
Java has a very complicated overloading design that includes overloading by static types.
19+
Overloading on types mixed with type inference might be very confusing.
20+
However, overloading based on arity is very simple and clear.
21+
Java also forces the writer of the function to write out a new function signature for every possible variant.
22+
A nice syntax for optional parameters is preferable to the Java approach.
23+
24+
So `to_str_radix(&self, radix: uint) -> String` can be now written as `to_str(&self, ?(radix: uint))`
25+
Since this is sugar for full overloading, a function declared with an optional parameter like this satisfies both
26+
```rust
27+
pub trait ToStr {
28+
fn to_str_(&self) -> String;
29+
}
30+
```
31+
32+
and
33+
34+
```rust
35+
pub trait ToStrRadix {
36+
fn to_str(&self, radix: uint) -> String;
37+
}
38+
```
39+
40+
traits.
41+
42+
Inside the body of the function, the arguments will be pattern matched something like this:
43+
44+
```rust
45+
let rad = match args {
46+
[_, radix] => radix,
47+
_ => 10
48+
};
49+
```
50+
51+
This allows for default arguments or actually doing completely different in each case.
52+
53+
This will let Rust get rid of the sheer multitude of functions that only differ by a few parameters like
54+
`concat` and `connect`; `split` and `splitn`. You can even go further and have a boolean indicating whether to
55+
use terminator semantics and put that into `split`, eliminating `split_terminator`.
56+
You could also have another boolean indicating whether it is reversed, eliminating `rsplitn`.
57+
58+
In this way, the library design is better, allowing auto-completion on `split`.
59+
There are less names in the std library. Some naming problems go away.
60+
61+
The easiest design is to allow all trailing parameters to be optional.
62+
That means that no mandatory parameter can come after an optional one.
63+
This design still allows to simplify naming in the standard library before 1.0 ships and the names are set in stone.
64+
Further refinements like trailing varargs, keyword arguments are possible in a backwards-compatible way.
65+
66+
# Drawbacks
67+
68+
Currently, you are able to write a function that differs by name to achieve the same effect.
69+
This works for `slice_from` and `slice_to` and `slice`.
70+
They are aptly named for what they do and can be easily autocompleted.
71+
However, just one `slice` with two optional args (defaulting to 0 and the length of the string)
72+
is much more elegant and doesn't clutter up the standard library with extra functions.
73+
74+
Of course, as I mentioned earlier, this also interacts with traits since now you satisfy two traits with one function.
75+
This probably interacts with closures and/or lifetimes in some way as well.
76+
So the correct standard library design must be weighed against adding yet another feature to Rust.
77+
78+
# Alternatives
79+
80+
Another proposal is to somehow represent optional arguments as some kind of an Option type.
81+
The drawback of this proposal is that Option is a library type. It would have to be baked into the language instead.
82+
83+
Another alternative is to keep the full overloading syntax. This eliminates having to destructure the args array.
84+
While this makes it a pain to rewrite all the possible variants, it's extremely explicit and clear.
85+
If you want either one or three arguments only, it won't accept two.
86+
For any function with k mandatory parameters and n total parameters the current proposal accepts all arities between k and n.
87+
88+
An alternative to trailing optional arguments is keyword arguments. This allows optional arguments in any place as long as
89+
the following required arguments or following optional arguments are called by their keywords to resolve ambiguities.
90+
This proposal has the downside of a more complicated argument resolution system (allowing some arguments to be called by position
91+
and some by keyword). It can also be implemented in a backwards-compatible way post 1.0 so it's not a 1.0 priority.
92+
93+
# Unresolved questions
94+
95+
If destructuring the arguments array is necessary, should there be some kind of a keyword for them.
96+
Is there any way to implement it without using a keyword, other than Java-style overloading?
97+
98+
If varargs are included in the proposal, then the `main` function could be written as
99+
100+
```rust
101+
fn main(...arguments: String)
102+
```
103+
104+
which could be nice. But then again, using std::os::args() is not a huge problem.

0 commit comments

Comments
 (0)