# Struct sugar

**URL:** <https://internals.rust-lang.org/t/struct-sugar/551>\
**Category:** ideas (deprecated)\
**Created:** [September 24, 2014, 2:09pm UTC](https://internals.rust-lang.org/t/struct-sugar/551 "2014-09-24T14:09:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![arcto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arcto/32/45_2.png) [@arcto](https://internals.rust-lang.org/u/arcto)\
**Post date:** [September 24, 2014, 2:09pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/1 "2014-09-24T14:09:45Z")

</div>

I’d like you to consider two ideas for making it easier to work with structs. I don’t know if these ideas are utterly crazy:

- Sugar for default field values.
- Implicit struct instantiation as function argument.

**This is what I would like to be able to write:**

```
struct A {x: int = 100, y: int = 1000}

fn main() {
    foo(x:12);
}

fn foo(a: A) {
    println!("{} {}", a.x, a.y);
}

```

**This is what you would have to write today:**

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

struct A {x: int, y: int}

impl Default for A {
    fn default () -> A {
        A {x: 100, y: 1000}
    }
}

fn main() {
    foo(A{x:12, ..Default::default()});
}

fn foo(a: A) {
    println!("{} {}", a.x, a.y);
}

```

So, basically specify the default values in the `struct` definition instead of using a `Default` trait. And, when calling a function that takes a `struct` leave out the struct name (known at compile-time anyhow from the function signature) and the also leave out brackets.

A function that borrows a `struct` would probably do so implicitly from the call point. Does it matter? It’s just an r-value.

---

<div class="post-metadata">

**Author:** ![pnkfelix](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pnkfelix/32/110_2.png) [@pnkfelix](https://internals.rust-lang.org/u/pnkfelix)\
**Post date:** [September 24, 2014, 3:14pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/2 "2014-09-24T15:14:52Z")

</div>

I would prefer to see something like this rather than incorporating keyword arguments into the function declaration syntax.

I had previously put up informal suggestions for ways to:

- try to get rid of the `..Default::default()` boilerplate here: [https://github.com/rust-lang/rust/issues/6973#issuecomment-22579034](https://github.com/rust-lang/rust/issues/6973#issuecomment-22579034) and then later,
- suggesting default const-expressions for structs here: [https://github.com/rust-lang/rust/issues/6973#issuecomment-24123745](https://github.com/rust-lang/rust/issues/6973#issuecomment-24123745)

We even went so far as to discuss default args and keyword values in a weekly meeting a year ago (holy cow, a year ago…) : [https://github.com/rust-lang/meeting-minutes/blob/master/weekly-meetings/2013-09-17.md#number-6973--default-arguments-and-keyword-values](https://github.com/rust-lang/meeting-minutes/blob/master/weekly-meetings/2013-09-17.md#number-6973--default-arguments-and-keyword-values)

Not sure if any of this is actually helpful, but maybe seeing some of the conversations in context can help you get an idea of how receptive people might be.

---

<div class="post-metadata">

**Author:** ![arcto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arcto/32/45_2.png) [@arcto](https://internals.rust-lang.org/u/arcto)\
**Post date:** [September 24, 2014, 5:13pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/3 "2014-09-24T17:13:21Z")

</div>

Encouraging to see so much interest in and support for these sorts of ideas!

In the proposal above, the implicit instantiation would only be applied when the `struct` is the _only_ formal parameter. I suppose that this would simplify the rules a lot, so as to not having to get tangled up with overloading. I believe this to be completely unambiguous.

---

<div class="post-metadata">

**Author:** ![krdln](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/krdln/32/7081_2.png) [@krdln](https://internals.rust-lang.org/u/krdln)\
**Post date:** [September 24, 2014, 8:55pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/4 "2014-09-24T20:55:57Z")

</div>

I really like the idea of using just structs and syntax sugar for keyword arguments! Even wanted to propose same thing.

I think that this sugar it could be extended to be used in any expression of already inferred type, not only in function arguments. For example:

```
struct Point {x: int, y: int};
fn here() -> Point { x: 1, y: 2 }

let v: Vec<Point> = Vec::new();
let p = x: 2, y: 4;
v.push(p);

```

Surrounding fields with `{}` could be possible too, and necessary for nesting:

```
struct Line {a: Point, b: Point}
fn fromZero(p: Point) -> Line { a: {x: 0, y: 0}, b: p }

```

I think it wouldn’t be ambigous and hard to parse and it would make it easier to DRY. What do you think?

Edit: It could work in patterns too (with obligatory `{}`).

---

<div class="post-metadata">

**Author:** ![arcto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arcto/32/45_2.png) [@arcto](https://internals.rust-lang.org/u/arcto)\
**Post date:** [September 24, 2014, 10:11pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/5 "2014-09-24T22:11:17Z")

</div>

```
fn here() -> Point { x: 1, y: 2 }

```

This looks awesome, but I’m not sure it’s entirely unproblematic. Can x be interpreted as a label?

---

<div class="post-metadata">

**Author:** ![krdln](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/krdln/32/7081_2.png) [@krdln](https://internals.rust-lang.org/u/krdln)\
**Post date:** [September 25, 2014, 5:32am UTC](https://internals.rust-lang.org/t/struct-sugar/551/6 "2014-09-25T05:32:30Z")

</div>

Label names have to start with apostrophe (as in lifetimes). But even if Rust would get rid of apostrophes, that wouldn’t create ambiguity, because label has to be followed by `loop`, `while` or `for`.

Changing `:` to `=` in struct declaration, as it was proposed, will break everything though.

---

<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:** [September 25, 2014, 7:00am UTC](https://internals.rust-lang.org/t/struct-sugar/551/7 "2014-09-25T07:00:23Z")

</div>

A side benefit of this would be being able to specify defaults for only part of a struct, while requiring the rest to be specified at instantiation.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 25, 2014, 9:17am UTC](https://internals.rust-lang.org/t/struct-sugar/551/8 "2014-09-25T09:17:32Z")

</div>

This looks very ergonomic. I would like to see this idea pursued further. I have lots of places where this could make the code shorter.

---

<div class="post-metadata">

**Author:** ![krdln](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/krdln/32/7081_2.png) [@krdln](https://internals.rust-lang.org/u/krdln)\
**Post date:** [September 25, 2014, 9:51am UTC](https://internals.rust-lang.org/t/struct-sugar/551/9 "2014-09-25T09:51:20Z")

</div>

I want to share some more thoughts: I think we want to be able to differentiate between using defaults on purpose and just instatiating a struct which happens to have a default. For example, let’s say `Vec3` has a default, and you are passing it to a function:

```
foo(x: 1, z: 3); // forgotten y

```

So I propose to add an obligatory `..` at the end, if your intention is to use defaults:

```
bar(param: 42, ..); // which would desugar into
bar(ParamStruct{param: 42, ..Default::default()});

```

Furthermore, we can add an struct attribute forbiding usage of such a struct without `..`. That would allow to create apis which can add fields to struct without breaking backward compatibility.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 25, 2014, 10:00am UTC](https://internals.rust-lang.org/t/struct-sugar/551/10 "2014-09-25T10:00:14Z")

</div>

For safety, ‘…’ could be required unless you specify the attribute.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 25, 2014, 10:09am UTC](https://internals.rust-lang.org/t/struct-sugar/551/11 "2014-09-25T10:09:08Z")

</div>

This makes a pattern nicer where enum variants wraps a struct:

```rust
Update(dt: self.dt);

```

vs

```rust
Update(UpdateArgs { dt: self.dt });

```

When matching:

```rust
match e {
    Update(dt: dt) => { ... }
}

```

With if let syntax:

```rust
if let Update(dt: dt) = e {
    ...
}

```

---

<div class="post-metadata">

**Author:** ![arcto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arcto/32/45_2.png) [@arcto](https://internals.rust-lang.org/u/arcto)\
**Post date:** [September 25, 2014, 10:23am UTC](https://internals.rust-lang.org/t/struct-sugar/551/12 "2014-09-25T10:23:49Z")

</div>

I don’t think that more than one `..` per struct would be necessary, though. Also, default values are supposed to be safe and unsurprising. So, I’m not sure the `..` marker is really needed.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 25, 2014, 7:22pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/13 "2014-09-25T19:22:36Z")

</div>

Would like to see this idea developed into an RFC. If this will have huge impact on the syntax, perhaps the RFC will be too much work for one person? How can we progress on the idea?

---

<div class="post-metadata">

**Author:** ![Manishearth](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/manishearth/32/50_2.png) [@Manishearth](https://internals.rust-lang.org/u/Manishearth)\
**Post date:** [September 25, 2014, 10:00pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/14 "2014-09-25T22:00:02Z")

</div>

There’s a small point of inefficiency in the current usage of `Default`; with default fields the compiler _should_ be compiling to a set of steps like:

- Create an instance of A with field x as the specified one and the rest of the fields as [default options here]

it currently compiles to

- Call the `default()` method, store its result in a temp var
  - Go up the call stack (Can be removed with an `#[inline]`)
  - Create an instance of A where all fields are the default
  - Return it (going down the call stack)

- Now, set the value of the field `x` to the specified value

Aside from the extra fiddling that the method call brings in, here we’re assigning to `x` twice. Which could be a heavy operation if `x` was something other than a number.

IMO, sugars shouldn’t be less performant than their expanded forms.

I like the proposed sugar, though I’m not too fond of theproposal for kwargs – what happens if there are two arguments?

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 26, 2014, 3:24pm UTC](https://internals.rust-lang.org/t/struct-sugar/551/16 "2014-09-26T15:24:28Z")

</div>

In cases where non-static expressions are needed, we could have some sugar for `Option`:

```
pub struct SliceArgs {
     pub from: Option<uint>,
     pub to: Option<uint>,
 }

 pub fn slice(&self, SliceArgs { from = 0, to = self.len() }) {
     ...
 }

 foo.slice(..);
 foo.slice(from: start, ..);
 foo.slice(to: end, ..);
 foo.slice(from: start, to: end);
```

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 28, 2014, 6:19am UTC](https://internals.rust-lang.org/t/struct-sugar/551/17 "2014-09-28T06:19:16Z")

</div>

It seems that sugaring for Default should be avoided of performance concerns and the disagreement of a proper default value.

Structs should simply allow default values.

To simplify parsing rules and allow macros where new struct members are intended withought breaking, the ‘, …’ at the end should be allowed even there are no members to initialize.

The parsing rules where ‘[]’ means optional:

```
[Foo] [{] (member: value),* [,] [..] [}]

```

- If the ‘{’ bracket is specified, it must be closed by ‘}’
- If a member is specified, a trailing comma is required
- If no member is specified, there should be no comma

One idea is to support unit structs in the same syntax, by allowing structs to be initialized without brackets:

```
..
UnitFoo
UnitFoo ..
Foo ..
Foo x: val, ..

```

If we go this route, I think ‘…’ should be mandatory whenever default values are used. The reasons are

1. to let the programmer control intention
2. provide unambiguous grammar when reading code.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 28, 2014, 7:49am UTC](https://internals.rust-lang.org/t/struct-sugar/551/18 "2014-09-28T07:49:07Z")

</div>

Option sugar can be added to simplify destructuring of members that are optional. This will also be used in function arguments to evaluate non-static expressions.

For non-static expressions left expressions, where ‘[]’ is optional, the parsing rules are:

```
Foo { ([member:] [ref] [mut] var [= empty_value]),+ , [..] }

```

- The type of the member must be an enum of type Option
- The struct name and brackets are mandatory
- Member is optional only if the variable name matches member name
- At least one member must be specified

The type must be Option because it needs to …:

- … be an enum
- … be unwrappable
- … have an empty variant
- … be declared in the struct (Result is not suitable)

Since there is only one value to unwrap, this leaves us with Option as the only candidate.

```
// No unwrap
let Foo {x, ..} = foo;

// Unwrap with default
let Foo {x = 3, ..} = foo;

```

The reason struct name is mandatory is because the compiler would not be able to infer the type otherwise. An alternative syntax is to leave out the struct name but require a type annotation.

Whenever the left argument type is Option, a right argument expression which type is not Option desugars to ‘Some(value)’.

```
let x: Option<uint> = 3;

```

When a struct takes no generic arguments, the type annotation is optional.

```
struct Bar { x: Option<uint> }

fn foo(Bar { x }) { ... } // No unwrap
fn foo(Bar { x = 3 }) { ... } // Unwrap with default

foo(x: 2)
foo(x: Some(2))

```

Option is the only type with a fixed default value, which is None. It is not possible to override this in struct definition. This is to avoid ambiguity.

```
struct Bar { x: Option<uint>, y: Option<uint> }

fn foo(Bar { x = 3, .. }) { ... } // Ignore y
fn foo(Bar { x = 3, y }) { ... }

```

When taking a struct by reference, the type annotation is required.

```
fn foo(&self, &Bar { ref mut x = 3, ref y }: &mut Bar) { ... }

```

Non-static expressions when unwrapping by default in functions, but must depend only on arguments before. This is to avoid cyclic dependencies.

```
// y depends on x
fn foo(Bar { x = 3, y = x + 2 }) { ... }

// y depends on self
fn foo(&self, Bar { x = 0, y = self.len() } { ... } 

```

A non-static expression can use brackets to execute arbitrary code.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 28, 2014, 8:27am UTC](https://internals.rust-lang.org/t/struct-sugar/551/19 "2014-09-28T08:27:26Z")

</div>

You should be able to return in the expression when it is None:

```
let Foo { x = return } = foo;

```

This is equivalent to:

```
let Foo { x } = foo;
let x = match x { None => return, Some(x) => x };
```

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 28, 2014, 8:50am UTC](https://internals.rust-lang.org/t/struct-sugar/551/20 "2014-09-28T08:50:47Z")

</div>

With this implemented, it will make sense to support named arguments and optional arguments with default.

```
// Unwraps and sets default
fn foo(x: uint = 3) { ... }

foo(..)
foo(4)

```

The syntax for calling is the same as for struct sugar. If one argument is named, then all other arguments must be named or use defaults. When using defaults, ‘, …’ must be added.

Option types are not allowed to have default argument value. It makes no sense to default them, since it defaults to None, and if you default to something else you do not need Option.

---

<div class="post-metadata">

**Author:** ![bvssvni](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bvssvni/32/4649_2.png) [@bvssvni](https://internals.rust-lang.org/u/bvssvni)\
**Post date:** [September 28, 2014, 9:11am UTC](https://internals.rust-lang.org/t/struct-sugar/551/21 "2014-09-28T09:11:27Z")

</div>

A similar sugar can be applied to struct tuples. This makes it easier to refactor struct tuples into structs and use them as arguments.

```
// Struct tuple syntax
let foo = Foo(x, y);

// Struct tuple sugar
let foo: Foo = x, y;

```

Unlike structs, it is not allowed to use parenthesis, because these are reserved for tuples. Mixing them would be confusing. This can be solved by using implicit casting from tuples to struct and struct tuples.

Struct tuples can be used in function arguments, but can only be desugared if it is the only argument beside ‘self’. Like structs, they do not need a type annotation if the type takes no generic arguments.

```
fn foo(&self, Foo(x, y = 0)) { ... }

foo(2, 3);
foo(2, ..);

```

Like structs, non-static expressions can be used as defaults in left arguments:

```
let Foo(x = 3, y) = foo; // Unwrap x with default

```

Like structs, return can be called in default expression.

Like structs, default expressions can depend on variables in scope and previous destructured values.

Unlike structs, struct tuples do not allow optional arguments. A value can be desugared to ‘Some(value)’. If one wishes to not specify a value, or one can type ‘None’.

[Next page](https://internals.rust-lang.org/t/struct-sugar/551.md?page=2)
