Swift has a pair of protocols, Encodable and Decodable, which represent generic encoding of a tree structure. These protocols are special in that the compiler can provide a default implementation for them under many circumstances. Similarly, Rust has a project called Serde which likewise is used for roughly the same purpose; Serde’s traits are even more complicated than Codable’s, but have even more powerful code synthesis via Rust’s proc-macros. Both tools are very useful but occasionally frustrating, and I think some of the frustrating areas come from a tension between two competing use cases.
Default Arguments and Label-based Overloading
This post is in response to Aria Beingessner’s “Defaults Affect Inference in Rust: Expressions Instead Of Types”, which describes how adding default arguments to Rust could help with some Rust stdlib problems around generics. At the same time, the Rust internals forum has a thread on “Named Arguments” something that’s been discussed for Rust off and on for years (at varying levels of seriousness).
Here I’m going to discuss how those two features interact, and why considering them separately is potentially a bad idea. It’s a lot more braindump-y than my usual style, so be warned. The post is written with a Rust audience in mind, but makes frequent reference to Swift, Python, and C# as examples of real-world languages that have some version of these features. It also overlaps quite a bit with Aria’s post.
This is going to be another one of those posts where I did something ridiculous and then show you how I got there, so let’s just get right to it.