I'm going to assume that there already is some interest on named arguments in Rust.
I have implemented a very early prototype that seems to suggest that we can implement these arguments in Rust without deep changes to the type system or compiler.
Basically, this lets us write:
// Define the function.
define!(fn rect(x: u32, width: u32, y: u32, height: u32, background: Option<Color> = None, foreground: Option<Color> = None, line: Option<Color> = None) -> Widget {
// ...
})
// Call the function, macro-style.
// Arguments are re-ordered as needed and optional arguments are replaced with their default value if needed.
call!(rect, x = X, y = Y, width = WIDTH, height = HEIGHT, line = LINE);
// Or, equivalently, builder-style.
rect::setup()
.x(X)
.y(Y)
.width(WIDTH)
.height(HEIGHT)
.line(LINE)
.call();
// On the other hand, the following fails to type-check, because we've forgotten
// required argument `height`.
call!(rect, x = X, y = Y, width = WIDTH, line = LINE);
// ... or equivalently
rect::setup()
.x(X)
.y(Y)
.width(WIDTH)
.line(LINE)
.call();
// And the following fails to type-check because we've used the same argument
// twice:
call!(rect, x = X, y = Y, x = X, width = WIDTH, height = HEIGHT, line = LINE);
// ... or equivalently
rect::setup()
.x(X)
.y(Y)
.x(X)
.width(WIDTH)
.height(HEIGHT)
.line(LINE)
.call();
The short of it is that we handle named and optional arguments by generating a type-level FSM that accepts only sequences of arguments in which all required arguments are provided and no argument is provided more than once. For a prototype, this can be done entirely in userland, at the cost of not-very-useful error messages.
I've posted more details on my blog.
I'd like to gather some early feedback and see if there's interest in me pursuing this work and possibly turning this into a RFC.
edit Fixed typo in example.