# \[Pre-RFC\] Keyword arguments

**URL:** <https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453>\
**Category:** ideas (deprecated)\
**Created:** [January 27, 2015, 1:59am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453 "2015-01-27T01:59:07Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [January 27, 2015, 1:59am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/1 "2015-01-27T01:59:07Z")

</div>

- Start Date: 2015-01-26
- RFC PR #: (leave this empty)
- Rust Issue #: (leave this empty)

# Summary

Add keyword arguments to Rust in a backwards-compatible way.

# Motivation

Allow another kind of argument in Rust. Current arguments distinguish themselves from other types by their order. If there is no semantic reason for a certain order, the argument order in functions is basically arbitrary. Consider a call like this:

```rust
window.addNewControl("Title", 20, 50, 100, 50, true);

```

First of all, the call tells nothing the user about what those values mean. Secondly, their order is arbitrary and must be memorized. What I propose is that this call would rather look like:

```rust
window.addNewControl(
    title => "Title", 
    xPosition => 20, 
    yPosition => 50, 
    width => 100, 
    height => 50, 
    drawingNow => true);

```

While you might argue that this is more verbose, a lot of libraries in JavaScript actually have a convention with calling with associative arrays like:

```rust
window.addNewControl({ xPosition: 20, yPosition: 50, width: 100, height: 5,
                 drawingNow: true });

```

If this wasn’t a convenient pattern, nobody would bother to do it.

An additional benefit is that this leads to an easy implementation of optional parameters and optional parameters. In languages like PHP, default parameters must come at the end of the function and must have a value. But in languages that support some sort of currying, not specifying the last parameter gives you a partially-applied function! This means that default parameters and currying/partial application are at odds with each other normally because you can’t tell when a function is partially-applied or has default parameter.

The design with keyword arguments doesn’t have this problem: you can execute the function when the last positional argument is given and list all the keyword arguments out of order. That means you can keep passing arguments to a partially-applied function and it won’t execute until the last positional argument is given. Furthermore, you can have optional parameters in the beginning, middle and end of functions without any restrictions other than that they have to be keyword arguments.

# Detailed design

Currently Rust has

```rust
fn slice(&self, begin: usize, end: usize) -> &'a str
fn slice_from(&self, begin: usize) -> &'a str
fn slice_to(&self, end: usize) -> &'a str

```

This can be changed to

```rust
fn slice(&self, from => begin: usize, to => end: usize) -> &'a str
fn slice(&self, from => begin: usize) -> &'a str
fn slice(&self, to => end: usize) -> &'a str

```

Note that these are three different functions that have three different signatures. The keywords a function accepts is part of its signature. You can call these functions like this:

```rust
foo.slice(from => 5); //equivalent to current foo.slice_from(5)
foo.slice(to => 9); //equivalent to current foo.slice_to(9)
foo.slice(from => 5, to => 9); //equivalent to current foo.slice(5, 9)
foo.slice(from => 9, to => 5); //equivalent to current foo.slice(5, 9)

```

if Rust had some kind of way to curry functions added later, you could curry the arguments and then manually pass the `&self` as the last argument to the function:

```rust
let x = curried_slice(from => 5); //curried
x(foo); //foo.slice_from(5);
let y = curried_slice(from => 5); //curried
let z = y(to => 10); //curried
z(foo); //foo.slice(5, 10);

```

So this feature is future-proof for a possible currying method in Rust. In JavaScript a lot of libraries cannot be used by some kind of a `curry()` function because the order of the arguments is wrong - the authors never considered that someone would try to curry their functions and partial application in JS is pretty useless because of this (you sometimes want to partially apply the SECOND argument and it’s painful to do this). Having a design that already solves issues with argument order is an indirect benefit.

# Drawbacks

This is a more complicated design than just having default arguments and overloading. Now there are two different types of arguments (positional and keyword) and they might interact with each other, lifetimes, traits, closures in different ways. It doesn’t solve the problem of currying when there are no positional arguments in the first place, so you need at least one positional argument to curry in a pain-free way.

# Alternatives

A better design to the above function might be designing it like so:

```rust
let title = "Title";
let position = Position(20, 50);
let dimensions = Dimension(100, 50);
window.addNewControlDrawingNow(title, position, dimensions);

```

Now the function takes three parameters, and we assigned them meaningful names. We have created two different functions `addNewControl` and `addNewControlDrawingNow` instead of passing a boolean to choose whether the control draws now.

While this design is better, it still doesn’t solve the problem of having to remember of what order to put `dimensions`, `position`, and the `title`. At least the compiler will now verify that the types are correct. It is still up to the programmer to actually name those variables well, instead of the API specifying what the keywords should be.

If keyword arguments themselves are not implemented, then there’s also the issue of overloading to enable better API design.

# Unresolved questions

Should closures have keyword arguments as well?

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [January 27, 2015, 7:40am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/2 "2015-01-27T07:40:36Z")

</div>

This actually sounds like how Objective-C’s selectors work (the “keyword argument names” are part of the method name and are compulsory).

Questions:

1. Are the keyword arguments unordered? Is `foo.slice(to => 5, from => 0)` valid?
2. Can keyword arguments be mixed with normal arguments? `fn foo(a: i32, b: i32, c => d: i32)`?
3. How do I take a function pointer from these functions?
  - What is the type of the function pointer?
  - If the function pointer type is not something simple like `fn(i32, i32) -> i32`, what is the representation of the corresponding Fn/FnMut/FnOnce trait, after desugared into `Fn<A, Result=R>` form?

4. [Bikeshed] Why `=>` is chosen? Note that `println!` uses `=` for named parameters. `:` cannot be used as it is reserved for type ascription.

I suggest “currying” / partial application be taken out from the RFC, it is orthogonal to the concept of keyword arguments.

---

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [January 27, 2015, 7:59am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/3 "2015-01-27T07:59:10Z")

</div>

1. I would prefer unordered so I don’t have to remember the exact order.
2. Yes, this is part of the design for optional arguments, the optional arguments will be keyword arguments and can be listed in any order (not just in the end).
3. If you want to have that, the type of the function pointer will be `fn(i32, up_to => i32) -> i32` which will not type check if you passed in a `fn(i32, i32) -> 32`. Its internal representation is the same, but it’s a different type.
4. This is because the design for default values of these parameters uses `=`

```rust
fn slice(&self, from => begin: usize = 0, to => end: usize = self.length)

```

or maybe even

```rust
fn slice(&self, from => begin = 0us, to => end = self.length)

```

Currying/partial application is orthogonal, but alternative designs like default type parameters make currying impossible from the end, and doing it from the beginning does not conform to expectations. This design solves that issue if it were ever to come up.

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [January 27, 2015, 9:13am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/4 "2015-01-27T09:13:39Z")

</div>

Regarding 3, I mean that currently `Fn(A, B, C) -> R` will desugar into `Fn<(A, B, C), R>`. Then what should `Fn(A, foo => B) -> C` become? This is actually about that unresolved question “should closures have keyword arguments as well”.

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [January 27, 2015, 10:04am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/5 "2015-01-27T10:04:52Z")

</div>

Why add additional keywords? The argument names are already there. Why not use those? Then any function would be callable this way, the order would be found by the compiler at the callsite.

bikeshedding: the `=>` operator reminds a lot of matches, instead do it like structs do it:

```
struct SuperArgs {
    cake : i32,
    colors : String,
    nothing : Option<i8>,
}
fn potential_future_func(colors : String, cake : i32, nothing : Option<i8>) {
    println!("{},{},{:?}", colors, cake, nothing);
}

fn super_func(args : SuperArgs) {
    println!("{},{},{:?}", args.colors, args.cake, args.nothing);
}

fn main() {
    super_func(SuperArgs{cake : 99, colors : "hi".to_string(), nothing : None});
    potential_future_func(cake : 99, colors : "bye".to_string(), nothing : Some(42));
}
```

---

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [January 27, 2015, 10:09am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/6 "2015-01-27T10:09:23Z")

</div>

Keyword arguments also give you the ability to overload functions by keyword argument.

So in fact I can have a function like:

`fn slice(&self, to => end: usize) -> &'a str` vs. `fn slice(&self, from => begin: usize) -> &'a str`

Notice that the signatures of these functions are both `usize -> &'a str` which is why they would still need a different name even if Java-style overloading would be added to Rust.

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [January 27, 2015, 10:25am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/7 "2015-01-27T10:25:41Z")

</div>

you are trying to do two things in one rfc. overloading and keyword arguments. I suggest you stick to the latter, as overloading could be added later (probably even backwards compatible).

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [January 27, 2015, 11:46am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/8 "2015-01-27T11:46:21Z")

</div>

As written above, `:` is will interfere with [type ascription](http://discuss.rust-lang.org/t/eliminate-redundancy-in-constructor-like-methods/523/4). Unless the names are compulsory, we should better not use `:`.

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [January 27, 2015, 12:03pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/9 "2015-01-27T12:03:58Z")

</div>

not quite, since you don’t add types in function calls, but only in function definitions

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [January 27, 2015, 12:25pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/10 "2015-01-27T12:25:03Z")

</div>

Variable namespace and type namespace can have overlapping.

```rust
use std::default::Default;

#[allow(non_camel_case_types)]
#[derive(Default)]
struct u128 {
    pub x: u64,
    pub y: u64,
}
fn foo<T>(u127: T) {
    /* what is type T if we allow both keyword args and type ascription? */
}
fn main() {
    let u127 = Default::default();
    let u128 = "1234";
    foo(u127:u128); // <--- note that foo(u128) works today.
}

```

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [January 27, 2015, 12:31pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/11 "2015-01-27T12:31:17Z")

</div>

as I said, in function definitions there’s a type after the colon. in functions calls (and today already in struct creation) it is an assignment/initialization.

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [January 27, 2015, 12:47pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/12 "2015-01-27T12:47:22Z")

</div>

Therefore in [http://discuss.rust-lang.org/t/pre-rfc-keyword-arguments/1453/8?u=kennytm](http://discuss.rust-lang.org/t/pre-rfc-keyword-arguments/1453/8?u=kennytm) I said **_unless the names are compulsory_** these two features will interfere if `:` is chosen. The keyword argument names must be _optional_ for 1.0-compatibility. You can write

```
fn potential_future_func(colors: String, cake: i32, nothing: Option<i8>) {}
potential_future_func("bye".to_string(), 99, Some(42));

```

today, and this should continue to work before 2.0. Struct creation work because the field names are _compulsory_ in the expression.

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [January 27, 2015, 1:45pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/13 "2015-01-27T13:45:06Z")

</div>

I don’t see how the following (including both named and positional arguments at the same time) would be incompatible to 1.0. Right now, colons in function calls don’t have any meaning, therefore they can be added in the future.

```
fn potential_future_func(colors: String, cake: i32, nothing: Option<i8>) {}
potential_future_func("bye".to_string(), nothing: Some(42), cake: 99);

```

If you mean the keyword-renaming( and overloading), then I agree, the renames can’t be separated from argument name and type by the colon operator in the function definition.

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [January 27, 2015, 1:47pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/14 "2015-01-27T13:47:34Z")

</div>

Please check [https://github.com/rust-lang/rfcs/issues/354](https://github.com/rust-lang/rfcs/issues/354).

---

<div class="post-metadata">

**Author:** ![oli-obk](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/oli-obk/32/3168_2.png) [@oli-obk](https://internals.rust-lang.org/u/oli-obk)\
**Post date:** [January 27, 2015, 1:59pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/15 "2015-01-27T13:59:33Z")

</div>

thanks, didn’t know about expression type ascription.

---

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [January 27, 2015, 5:22pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/16 "2015-01-27T17:22:30Z")

</div>

Well if I can’t talk about optional arguments/overloading/currying, then there are no benefits to keyword arguments over just passing in a struct!

I am talking about overloading and currying because they are the benefits of this design over just slapping on default arguments and calling it a day.

---

<div class="post-metadata">

**Author:** ![steven099](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steven099/32/3871_2.png) [@steven099](https://internals.rust-lang.org/u/steven099)\
**Post date:** [January 27, 2015, 5:33pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/17 "2015-01-27T17:33:43Z")

</div>

> [@kennytm](#):
>
> Regarding 3, I mean that currently Fn(A, B, C) -\> R will desugar into Fn\<(A, B, C), R\>. Then what should Fn(A, foo =\> B) -\> C become? This is actually about that unresolved question "should closures have keyword arguments as well".

There are two options that I see, which aren't mutually exclusive. One is to ensure that tuples mirror any feature you add to function signatures. So `Fn(a: A, foo => b: B) -> C` would desurgar into `Fn<(A, foo => B), C>`. The other possibility is to have a fully-specified syntax for keyword functions, like `func(=>foo)` which is assignable to `Fn<(A, B), C>`.

---

<div class="post-metadata">

**Author:** ![ruuda](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ruuda/32/1870_2.png) [@ruuda](https://internals.rust-lang.org/u/ruuda)\
**Post date:** [January 27, 2015, 11:31pm UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/18 "2015-01-27T23:31:17Z")

</div>

I am not necessarily opposed to this, but as for your example, note that you can do this:

```rust
struct ControlArgs<'t> {
    pub title: &'t str,
    pub x_pos: i32,
    pub y_pos: i32,
    pub width: u32,
    pub height: u32,
    pub drawing_now: bool
}

fn add_new_control<'t>(args: ControlArgs<'t>) { ... }

window.add_new_control(ControlArgs {
    title: "Title",
    x_pos: 20,
    y_pos: 50,
    width: 100,
    height: 50,
    drawing_now: true
});

```

Which for the caller is almost identical to the Javascript version and your proposed syntax. It lets you provide named arguments in an arbitrary order.

---

<div class="post-metadata">

**Author:** ![ArtemGr](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/artemgr/32/280_2.png) [@ArtemGr](https://internals.rust-lang.org/u/ArtemGr)\
**Post date:** [January 28, 2015, 12:15am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/19 "2015-01-28T00:15:58Z")

</div>

> Well if I can't talk about optional arguments/overloading/currying, then there are no benefits to keyword arguments over just passing in a struct!

Wouldn't overloading be also possible with a struct? I think the overloading shouldn't in any way depend on the keyword arguments and vice versa, they are different concerns. It would've been counter-intuitive if oveloading somehow depended on keyword arguments instead of being simply the general overloading like in other languages.

Overloading based on the keyword arguments looks like an interested idea, but why should it be special? Wouldn't people abuse it by emulating the normal overloading with keyword arguments, e.g. introducing unnecessary bloat by writing `foo (array => []); foo (map => my_btree_map)` instead of simply passing `foo ([]); foo (my_btree_map)`?

On the other hand, maybe the normal overloading isn't going to lend in Rust (any time soon), making the keyword argument based overloading desirable as a poor man's alternative?

As for benefits of keyword arguments, with a struct you can't use the positional arguments, you are forced to name everything, not to mention that it bloats the program's namespace and looks less ideomatic and takes the choice out of the hands of the caller. So the keyword arguments make a lot of sence even without the overloading, one can make a more readable code with them where and when it's necessary and without a need to modify the API. Thus, a concern I have with this pre-RFC is that it would clash with arguably better keyword arguments proposals, like this one [https://github.com/rust-lang/rfcs/pull/257](https://github.com/rust-lang/rfcs/pull/257).

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [January 28, 2015, 2:05am UTC](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453/20 "2015-01-28T02:05:38Z")

</div>

In my opinion (which I’ve explained before, not that anyone cares), freeform overloading is bad, keyword and optional arguments are good. Objective-C like mandatory keywords are nice for self-explanatory code, at least if you have an IDE, but very different from regular keywords+optionals, because they only achieve the same purpose (allow you to omit arguments) if you add overloading. (You’ll notice that most Objective-C methods are highly verbose and take a lot of arguments…) Python-like keywords+optionals are a good way to not have to create a bunch of helper methods to do the same thing with slightly different variations on how much is specified, but that’s exactly what overloading forces you to do.

However, Python’s system has problems, especially related to the propagation of arguments and defaults to wrapper methods. I think my preferred system would basically be a way to mark a function so that it automatically creates an argument wrapper struct when called (which can then be passed directly to other functions without re-specifying each argument, etc…).

[Next page](https://internals.rust-lang.org/t/pre-rfc-keyword-arguments/1453.md?page=2)
