Could we have `std::default()`?


#1

I’m getting tired of Default::default() everywhere. I’d like to do just default().

Could we have std::default() or std::default::default() like this:

fn default<T:Default>()-> T {
   std::default::Default::default() // gosh, that's a lot of default, isn't it?
}

?

This way I could just use std::default and “be lazy”. I think readability wouldn’t suffer (quite the opposite!) - Default is so common and idiomatic, the name of the function explains it all, Default:: prefix is just stuttering, and the definition is just one racer jump away anyway.


[Pre-RFC] Automatic initializers
#2

I do wish it was possible to do something like

use Default::default;

so that when I say default it means Default::default


#3
<_>::default()

It’s even the same number of characters.


#4

I do wish that too… but it could be tricky from the POV of the type system… Namely, what do you do with the type parameters of the function and where do you put the type parameter needed for T: Default – can you specify it even (or is it a sort of arg: impl Trait kinda thing)?


#5

Same as? Definitely longer than just default().


#6

As std::default(). You’d have to use default 4+ times for the use to be worth it. Even then, <_>:: is not so hard to type, so I never bother trying to shorten it more.


#7

My code is typically very heavy with default. Default trait is just a wonderful idea, and I implement it for every type for which it makes sense.

Typing <_>:: is a chore, come on.

Also, just look at Default::default() or <_>::default(). It’s just eye soring. It must make people reading Rust code think there’s something terribly wrong with the language when people just keep doing it. Either stuttering or some weird characters. Meh.


#8

All of that is subjective, and I don’t agree with any of it. I have no problem typing or reading <_>::. I use Default all the time, and don’t even have to think about the <_>:: part.


#9

There’s an open issue about this somewhere in rust-lang/rust or rust-lang/rfcs repo.
This is certainly possible and more or less equivalent to use Enum::Variant;, someone just needs to do the implementation.


#10

It’s nice to see that the ecosystem now gravitates more towards Default instead of argumentless new() functions.

I’ve been thinking about a possible feature that may be related and may also reduce the need to explicitly type Default::default() over and over again - it’d be nice if we could use partial FRU/auto-derive for the Default impl.

From my experience, structs usually have a few key data members that have to be explicitly initialized but also have a lot of supplementing data, all of which can be Default::default()ed.

So instead of:

MyData {
    aux: important_bit.something(),
    key: important_bit,
    supp1: Default::default(),
    supp2: Default::default(),
    // ...
}

we could have:

MyData {
    aux: important_bit.something(),
    key: important_bit,
    _: Default::default(), // open for bike-shedding
    // ...Default::default() FRU not possible since there's no `impl Default for MyData`

Would that be considered useful and not expend the language complexity/quirkness budget?


#11

Personally I think https://github.com/rust-lang/rfcs/pull/1806 is the beautiful approach in this design space.


#12

Ah, makes sense that someone else thought about that. Thanks for the link!


#13

It seems that discussion turned into improving A { a, b, c .. Default::default()} which I’m also happy to see, but that’s not covering everything.

Sometimes I just have.

#[derive(Default)]
struct Foo { ... }

and in my code I’d like:

let foo = default();

instead of

let foo = Default::default();

I don’t know… I guess I’ll just make a crate for myself and go with that. ¯\(ツ)


#14

There’s probably already “extended prelude” crates on crates.io, you could ask one of them to add this.


#15

I also would like to have an ability to import static trait methods.

Yes, I think such parameters should be inferable-only.

UPD: Here is the relevant issue.


#16

These days I tend to use the following style:

let foo = Foo::default();

I find it visually more appealing and conveying more information.


#17

You don’t even need a crate for a simple one liner.

fn default<T: Default>() -> T { Default::default() }

#18

https://crates.io/crates/default

This crate implements standalone default() function that can be imported with use default::default; and then in your code you can just:

let foo = default();

instead of the usual:

let foo = Default::default();

(For visitors to the thread)


#19

I prefer to encourage the style @stjepang shows, in which the type is included in the expression, to help keep things clearer. Unless you’re doing Foo { bar, baz, ..Default::default() }, in which cause its clear enough.


#20

I like that. Though in many cases I would rather have type inference figure out the type since the variable name makes it already obvious to the reader.

Anyway, since I made a crate, now in Rust 2018 edition I can literally do use default::default;, which is even better than use std::default::default();. :smiley: