Why doesn't Rust have record types?
I keep thinking about this every couple of months. Rust has structs, tuples and tuple structs. I feel like records are the obviously missing piece to this story. Consider this perspective:
| nominally typed | structurally typed | |
|---|---|---|
| named fields | structs | ?? records ?? |
| ordered fields | tuple structs | tuples |
Why do such records not exist? Is there some specific reason it was judged as undesirable? Was it unclear how to implement them efficiently? Or was there simply no convincing enough use case to add them? (Which would be a valid reason imo, I'm not in favor of more features without clear benefit.)
Here are a couple use cases that come to my mind. All of them are quality-of-life stuff, nothing groundbreaking. (I think tuple structs are pretty much just syntax sugar as well, right? Nothing you can do with it that cannot be done with a regular struct.)
- Named arguments. Just have a single argument of some record type an destructure it immediately in the function signature. Calling such a function:
foo({ arg_bar, arg_baz }). (Can be achieved with Structs, but then you need to name the struct explicitly to pass the arguments, which means you might have to import it... very verbose.) - Make large tuples more manageable. Tuples with many fields can become unwieldy, especially when some of the fields have the same type. Which one is which? Confusing them might be dangerous. Giving the fields names solves that problem.
- This is not a necessary feature, but I think it would be brilliant: The spreading operator could be used to get subsets of some record. e.g.
I am imagining a record holding "options" that can be passed along from function to function. The lower functions in the call chain might accept a smaller selection of options, so the spreading operator could be very useful.fn foo(args: { a: i32, b: char }) {} let rec = { a: 42, b: 'x', c: "hello" }; foo({ ..rec });
Problems that come to my mind:
- Can this be done without a parsing ambiguity?
let rec = { /**/ }exists already, where the curly braces are a block. Some languages use#{}for records I think. I'm not a huge fan of this proliferation of operators and symbol combinations.
I wonder what other people think about it and what considerations I might be missing.