I’ve just came up with an idea!
Sorry, if this is not new idea, I know that there were serveral discussions on the subject, and I briefly read them.
Idea
I propose unification of syntax of
- structs
- tuple structs
- tuples
- funcitons
- introduction of function named arguments
- introduction of tuples with named fields
- introduction of function parameter default values
Current state
Currently Rust has five objects that has value arguments: structs, tuple structs, tuples, functions (and closures).
Syntax of construction/call of these things:
struct Foo { a: A, b: B } // struct
struct Baz(A, B) // tuple struct
(A, B) // tuple
fn baz(a: A, b: B) -> ... // function
Syntax of calling these things:
Foo { a: a, b: b }
Bar(a, b)
(a, b)
baz(a, b)
And, these things have member access operators:
foo.a
bar.0
tuple.0
(not appilcable to function calls)
So, my idea is this
- No curly braces in structs
- all struct fields have indexes, some fields have names
- so tuple structs are just structs with all fields without names
- tuples are anonymous structs with the same rules
- function call arguments is the same thing (to some degree) as tuples
So, objects that I described before, now written as:
struct Foo(a: A, b: B) // like function declaration
// and the rest as before
struct Bar(A, B)
(A, B)
fn baz(a: A, b: B) -> ...
and invocation syntax (using .a =
instead of colon):
(I prefer .a =
to =>
syntax, because of similarity to C and to field access operation, but that’s not important right now).
Foo(.a = a, .b = b)
Bar(a, b)
(a, b)
baz(a, b)
However, the best thing is that this syntax allows intermixing of named and positional arguments!
Foo(a, .b = b) // Foo(.a = a, .b = b)
Bar(.0 = a, .1 = b) // Bar(a, b)
(a, .1 = b) // (a, b)
baz(a, .b = b) // the same as baz(a, b)
That’s it!
And also, note side effects:
Struct delcarations can mix positional and named fields
struct Foo(A, B, c: C, d: D, e: E, f: F)
Tuples can have named fields
fn get_host_and_port() -> (host: String, port: u16) { ... }
let host = get_host_and_port().host; // or .0
Default values
Probably this change should come together with function parameter default values (and because structs and functions are unified, struct may have default field values too):
fn connect_to_http_server(host: String, port: u16 = 80) { ... }
struct HttpConnection(host: String, port: u16 = 80)
connect_to_http_server(host) // use default port
HttpConnection(host) // use default port, do not specify field name
Syntax ambiguity
This change resolves minor syntax ambiguity when parsing if with struct. This code is not allowed now:
if Foo { a: 10 } == foo { ... }
This will be allowed:
if Foo(.a = 10) == foo { ... }
Last words
This is not a final proposal, there are thousands of things to be thought about. Please let me know! Especially if I missed something.