Who is even the target audience of this post? Beginners (which included all of us once) ask for all sorts of things. But these features didn’t happen in Rust for a reason.
Named parameters are not needed in the age of LSP hints, where this exists as an editor feature (including (neo)vim).
But if you really want named parameters AND optionals/defaults, rust always allowed the args struct pattern:
struct Args<'a> { a: &'a str, b: u64, c: Option<u64>, } impl<'a> Default for Args<'a> { fn default() -> Self { Self { a: "hi", // default b: 3, // default c: None, // optional default } } } takes_args(Args{a: "not hi", ..Args::default()})The builder pattern is more about valid initialization, but does interact with the arg struct pattern when you have non-default (forced) arguments, although even then, you can not use it by having:
struct Args<'a> { forced_arg1: &'a str, forced_arg2: u8, defaults: DefaultArgs, // implements Default }So mentioning the builder pattern is out of place.
Overloading is not used because we have traits (and the sound subset of specialization for when that’s needed).
So all in all, those “features” didn’t make it to Rust not because of the backlog, or for simplicity’s sake, but because idiomatic Rust (and even modern tooling in general, a la LSP) have alternatives that give you what you want and more.
Everything mentioned above should be known by anyone who knew Rust for more than a month.
I’m used to named arguments from other languages, and that makes me fairly partial to them. Having to tool around with builders feels a lot more complex and clunky.
That said, I do wonder at how many of the usecases aren’t workarounds for long argument lists that are either stringly typed, or something similar. As in, with a signature of
(i32,i32,i32,i32) -> whatever, named arguments seem like a way of getting the compiler to catch errors in confusing{x,y}_{position,length}; but if the signature were newtypes likeRect(Origin(i32,i32), Size(i32, i32)) -> whatever, then the felt need for named arguments drops considerably.With newtypes you can also emulate named args with a single struct. This also allows them to be passed on together.
struct RectArgs{ x:i32, y:32, w:32, h:32, } impl Default for RectArgs{...}Then the call site looks like this:
rect(RectArgs{ x:0, y:0, w:30, h:20, } // with default arguments rect(RectArgs{ w:30, h:20, .. RectArgs::default () }Yeah, though in those cases you might get an extra question about why
rectis a function and not a method, e.g.Rect { w: 30, h: 20, .. RectArgs::default() }.do_the_thing()I assumed the rect is a method on something like a graphics context or physics engine, but yeah.
Yeah, decent assumption, I’ll tone down my comment a bit.
This greatly depends on language design and implementation.
For example, Clojure has all of these and much more, and it’s still much simpler and hassle free than rust. The functions are just functions, but the forms and lists that are very powerful.
functions are just
(defn foo [a b] (print "do thing")) (foo 1 2)With the power of destructuring that maps provide us, we can have named arguments:
(defn foo [a & {:keys [b c]}] (print a b c)) (foo 1 {:b 2, :c 3})and for multi-arity functions, there’s no special syntax. It’s still just plain functions and forms
(def foo ([a] (print "I only have one" a) ([a b] (print "I have two" a b)))It also has more advanced ways of polymorphysm with methods and protocols.
It depends on the design of the language.
No.
YES!
Is this the 5 minute argument?
Well it WAS the 5 second argument.
Is it when you pick up an argument someone dropped?
I don’t know, it looks like the amount of issues is way higher than improvement in comfort. Beside, they mentioned a lot of corner cases that would definitely show up and become a problem
I’ve been using C++ for quite some time, and it also had some talks about having named parameters, but it only helps in some places and hinders in most, imo. I feel like in Rust you may use a struct as parameter containing all of function parameteres where you really want the names
Maybe






