3 ms·
Automatically generated builders are also nice, not sure yet which I prefer.
by MrBuddyCasino 6y ago
Automatically generated builders are also nice, not sure yet which I prefer.
- oefrha 6y agoBuilders are nice when you actually need to build something with tons of optional arguments. The vast majority of cases where named arguments shine are function/method calls where builders just don’t make sense. Also, named arguments complement/augment the builder pattern.
- MrBuddyCasino 6y agoGood point. Also, named arguments can be compiler checked for mandatory values, with builders the error happens at runtime.
- swsieber 6y agoYou can actually have type safe buildrs in rust where trying to call the method that consumes the builder fails to compile if not all the arguments are set correctly. https://github.com/idanarye/rust-typed-builder/blob/master/README.md#rust-typed-builder https://github.com/idanarye/rust-typed-builder/blob/master/R...
- MrBuddyCasino 6y agoAh yes, linear types to the rescue! Nice.
- swsieber 6y agoI think technically it's affine types. In this particular case it comes from really nice generics - you start out with a struct that's generic over all fields - one generic bound per field. And that let's you implement methods depending on what fields have been set. So you could even make a builder with mutually exclusive setters. But you'd probably just want to use an enum in that case for the mutually exclusive options.
- MrBuddyCasino 6y agoI still don't quite understand the generics magic required in order to not generate exponential amounts of code for it to allow random order of arguments, but I won't complain. That capability would have come in handy on Java/Lombok.
- swsieber 6y ago> exponential amounts of code for it to allow random order of arguments The key is that it only generates code for types that actually get used. So if you always call the orders in the same order, it won't generate tons of code. That said, you could actually tweak the type-safe builder to enforce a certain order for calling the methods on the builder. Also, it's not the order of arguments, it's the order of method calls :)
- kevincox 6y agoI have long envisioned a language where these two things were tightly combined. The rough ideas are: - All arguments are keyword arguments. - Each function implicitly defines a struct type equivalent to its arguments. I think if you combined this with some nice structural typing you can get a lot of the argument forwarding/builders and similar that people enjoy in dynamic languages without much/any overhead. Rough example: fn add(a: int, b: int): int { a + b } fn add3(c: int, rest: add::args): int { add(rest) + 3 } A somewhat silly example but I think you can see the point. Of course you could also add language-level builder syntax to these structs and have something really nice. I think the key here is that once you make the arguments a static type you can add loads of convenience like builders very easily.
- wwright 6y agoThis makes me wonder if there is some sort of relationship between currying and row polymorphism; that could be pretty sweet to capture succinctly in a language
- eeereerews 6y agoI've thought about this too, but keeping positional args. The basic data type would be a "blob", consisting of a struct part and a tuple part.
- MrBuddyCasino 6y agoArgs reified as structs, interesting! On the other hand, not exceptional at all when looking at it from a Lisp angle.