5 ms·
The article is wrong. Rich Hickey is talking about the surface of the function, interface. The implementation details do not matter in this case.
by XVincentX 3y ago
The article is wrong. Rich Hickey is talking about the surface of the function, interface. The implementation details do not matter in this case.
- riffraff 3y agoThe article is claiming that the surface and the implementation are related. If client code passed a null value before, an error would have occurred. Now it is handled with a default that the original code was not accounting for, and this might be bad. Thus the change in interface _is_ a change in behavior.
- saulpw 3y agoWhich no client should/would have been using (given the error they would have received). Why would this new implementation be presumed incompatible, when any reasonable person would think this is an addition to the interface, and not a difference to the existing interface?
- omnicognate 3y ago> no client should/would No client could, even. He's talking about static types so it wouldn't have been possible even to express a caller not providing a value.
- wk_end 3y agoIf the code passed in a null value before, it was violating the contract the function provided. A component isn't responsible for what happens when you operate it out of spec. If I were a hardware designer and some changes to an IC I'm working on are going to make the next batch, say, work properly in hotter temperatures than it could before, and one of my coworkers comes and says, "Don't make that change, what if someone using that IC is deliberately operating it out of spec expecting it to fail and now the behaviour is going to change!" I'm going to start polishing up my resume, because I'm working for an organization that employs lunatics. Happily, that wouldn't happen in the hardware world; unhappily, I'm a software developer rather than a hardware designer.
- heisenzombie 3y agoRelevant XKCD, "keyboard heating": https://xkcd.com/1172/ https://xkcd.com/1172/
- PaulDavisThe1st 3y agoThe caller could NOT pass a null value before. Old situation: called function says: "i would crash if you gave me a null value, so my interface says you cannot give me a null value" New situation: called function says: "i no longer crash if given a null value, which you couldn't do before anyway, so you won't notice any difference"
- tmountain 3y agoI believe this is exactly what Hickey was arguing.
- xmcqdpt2 3y agoBut they could pass null, though. Clojure doesn't stop you from passing null anywhere. Also, thrown exceptions are values. Consider for example a function that searches for a file a return null if it's not found, which you are composing with a function that opens a file but throws on null. You might very well write something like open(search(...)) and catching exceptions above that level. Now if I make open(..) able to accept null (maybe it opens a temp file?) then you now need to add a null check on the return value of search to get the old behaviour. That is 100% a breaking change!
- kybernetikos 3y agoBut you already had to have a null check on on the return value of search if open wasn't previously able to take null, so the behaviour of your code hasn't changed.
- xmcqdpt2 3y agoWhy? You may just have been catching the exception outside both functions. Lots of actual real-life programs, even if it's not the cleanest.
- PaulDavisThe1st 3y ago> Clojure doesn't stop you from passing null anywhere As a C++ programmer (oh, the horror!) I'd say that's an issue with Clojure rather than the general principle. And also one of the reasons I like the pointer/reference distinction in C++ (the former allows null values, the latter does not). But sure, that changes my interpretation somewhat. It doesn't really change program safety, however.
- kybernetikos 3y agoAlmost certainly, the behaviour for all possible values that could have been passed to the function has not changed, merely some new ones have been added. If that's true, then Hickey is right, it shouldn't be considered a breaking change. If at the same time as increasing the domain of the function, some of the return values changed for some possible values, then it is a potentially breaking change (although one not necessarily reflected in the API), and needs to be communicated. Whether it really is considered a 'breaking' change will depend on a fuzzy evaluation of whether it was legitimate for the client to make such assumptions about the return value, and will most likely depend on how the function was documented. That case, where the function returns different values to what it used to, and which may break code that had expectations about those values, is a change that can happen any time and is not really related to the question of what to do when a function domain increases.