3 ms·
You should categorically not be implementing chaining semantics unless your operations are non-mutating. If they are mutating and you return the same object, i
by ris 5y ago
You should categorically not be implementing chaining semantics unless your operations are non-mutating.
If they are mutating and you return the same object, it's possible for people to go years without realizing that's what's happening (no, most people don't read the manual), assigning the result to something else, reusing the original for another thing and introducing subtle bugs all over the place.
See the design of python's list `.sort()` returning None for this exact reason.
(and of course there are sometimes performance penalties to implementing non-mutating methods, so there are lots of valid cases for not implementing chaining semantics)
- eyelidlessness 5y agoThis is why I hate JS Array#sort. Its return type being an array gives the impression it’s not sorting the original array, leading to a lot of hard to track down bugs. It’s also one of the biggest reasons I discourage use of lodash. Sure, most of its methods are pure and return new values. But some do mutate the input, and they’re interchainable (sorry, couldn’t resist). The only way to know which you’re using is to memorize or constantly consult their enormous API.
- theteapot 5y ago> You should categorically not be implementing chaining semantics unless your operations are non-mutating. What if it's a method of the data object?
- Brian_K_White 5y agodata should not have methods, but that's a whole other religeous war :)
- nybble41 5y ago> What if it's a method of the data object? Then it should either mutate the object in-place without chaining, or return a new data object with the updated value and leave the original unmodified.
- hcrisp 5y agoOr at least adopt a semantic preference that informs the user as to what is happening, e.g. Python has .sorted() for for non-mutating method vs .sort() for mutating method.
- mgraczyk 5y ago`sorted()` is a builtin function, not a method. It can still be confusing, but it's more clear IMO that `sorted(array)` will not mutate vs a hypothetical `array.sorted()`.
- gpderetta 5y agoIn c++ you can make your mutating chaining operations rvalue qualified, have them return by value and move this into the result. So you have purely functional operations that still don't create copies in practice.
- AtlasBarfed 5y agoBuilder pattern for complex initialization like db connections
- timando 5y agoReturn a new builder that has the changes applied.
- brundolf 5y agoThis is something Rust is well-suited for (and it's a popular pattern in the Rust community as a result) Rust can a) enforce that a method is non-mutating on its object, and b) use move-semantics to return a "new" value without doing an actual clone, while preventing the "old" value from being reused elsewhere. So the immutable "builder" pattern works very smoothly and safely