`useReducer` is the most powerful core building block for state management in React 16.8, but its API is more complicated than it needs to be. `use-state-methods` offers a simpler alternative with no loss of expressiveness. Think in terms of "methods" which either mutate state or return a new state. No dispatching actions, no giant switch statements to handle them, and with free callback memoization.
They may be a tolerable layout for your set of apps, which tends to be pretty small, but for organizing all your files it quickly becomes a giant mess.
I tell you you have 12/0 apples. Write the number of apples you have on a piece of paper. Some "functions" are not defined for all inputs. Better to give a "that doesn't make sense" answer than a bogus answer.
Don't get me wrong, PHP is a joke of a language, but I don't see Rasmus as the one behaving childishly here, and I also don't think he's in the wrong. APIs are allowed to change in major releases, and the behavior the plaintiff was relying on was so clearly broken it boggles the mind that he would riddle his code with dependencies on it.
Even given that it was undefined behaviour to start with, it's the very first incompatible change listed at http://au2.php.net/manual/en/migration53.incompatible.php — you'd hope a professional developer would at least glance at that document when migrating a codebase to 5.3.
> Even given that it was undefined behaviour to start with
On the other hand, 1. high-level languages have no reason to have UBs, especially for the trivial calling of a core function and 2. one could expect behavior in this context to be coherent with behavior in userland contexts. In PHP, using strings in a numeric context wasn't — last time I checked — considered abnormal, no matter how little sense it makes. One could therefore expect the relevant coercitive calls to be performed as they would usually be.
> it's the very first incompatible change listed
It is very ambiguously worded: the clause states functions will return NULL when passed incompatible parameters, but in all of PHP's userland code strings are very much compatible with floats. I would therefore submit that — in the context of being a user of PHP — the clause does not apply to this case as the value passed in is absolutely compatible with parameter expectations.
> When a string is evaluated in a numeric context, the resulting value and type are determined as follows [...] The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero).
> 0 is hardly the standard identity value.
0 remains the standard and defined numeric value of an arbitrary string not prefixed with numeric data in PHP.
If a function in case of bad inputs returns a value in it's codomain, you can't distinguish it from a value returned by a normal call (except in cases where it falls outside of the functions image). This in my opinion is same as undefined behavior. Don't trust the value returned, if inputs were bad.
You know, I didn't actually know that. Thank you for enlightening me.
tools shouldn't rely on undocumented behavior when passing out-of-spec parameters into functions. Relying on such behavior eventually gets you what you deserve.
Or one could expect the language to behave coherently (tall orders for PHP, I know) and consider that it will use whatever is provided to it in the usual manner in which it treats non-numbers in a number context. Especially when the function has behaved in this manner for a decade.
As you note, one of the problems most cited with PHP is core language functions behaving in a non-coherent/non-consistent manor. This change was in-fact to bring this particular function in line with most of the others, i.e. to make it behave more coherently/consistently. It was documented, done in a major release, and done alongside a number of other (well publicised) breaking changes. Not everyone is going to be happy when things change, but I think this was a sensible development decision for the PHP team.
> This change was in-fact to bring this particular function in line with most of the others, i.e. to make it behave more coherently/consistently.
Well technically I believe it was done to unify argument parsing, but so far so good.
> to make it behave more coherently/consistently.
except this made all argument parsing (and especially this function) less coherent and consistent with PHP-the-actual-language: in PHP userland code, a string in a numeric concept will be implicitly converted to a number (to 0 if it is not prefixed by digits). This function used to behave coherently with PHP itself, as a language. Now it doesn't anymore. So all built-ins behave one way, the language itself behaves in the opposite way.
> It was documented
Not really, there was a note indicating plenty of shit broke (and it was ambiguous, the note says things about passing in incompatible parameters, but as far as PHP-the-language goes strings are compatible with floats), not listing functions which broke and in which manner.
With regards to consistency, aside from the fact that I don't think its easy or necessary to compare how functions deal with arguments to how syntax operators etc. deal with values, the situation prior to this change was that there was no consistency even within core functions themselves, before you even start to consider the rest of the language. This could have been resolved by changing all the other functions rather than these few, but that would have messed up a lot more userland code than this change did. I think it was the most pragmatic way of dealing with the issue.
With regards to the documentation, I'll concede that it could have been better. The previous behaviour was undefined and completely undocumented, so I think there are lessons for both "sides", 1) for the PHP team : fully document all changes, even to previously undefined/undocumented cases 2) for the users : don't implement functions in ways that are not documented (and/or santize input/validate output from functions used in such ways).
Also I don't think its strictly correct to say that strings "are compatible" with floats in PHP, rather that in most (but not all) cases strings will be treated/parsed down as floats.
> This could have been resolved by changing all the other functions rather than these few
What "these few"? As far as I know there is no list of the functions impacted by the change, how do you define that there's just a few versus not just a few of others?
> but that would have messed up a lot more userland code than this change did.
Because ponies? Where does that arbitrary and unsupported assertion come from exactly?
> I think it was the most pragmatic way of dealing with the issue.
Why? And why was it an issue in the first place?
> The previous behaviour was undefined and completely undocumented
The previous behavior was implementation-defined (as pretty much all of PHP is) and had been stable for a decade. And as I noted above, it was also coherent with userland behavior of PHP when dealing with strings in numerical contexts.
> Also I don't think its strictly correct to say that strings "are compatible" with floats in PHP, rather that in most (but not all) cases strings will be treated/parsed down as floats.
Which, for all intents and purposes, mean they're compatible with floats in most numeric contexts.
From the bug thread that this story refers to, Rasmus states "Most of PHP was using this already, but there were still some stragglers like number_format()". I think my arguments regarding impact of the change are a reasonable extrapolation from that.
Why was it pragmatic? Why was it an issue? There was inconsistency in the ways that functions handled parsing, and many people didn't want that feeling it made it harder to code correctly/consistently, thus it was an issue (part of the greater issue of inconsistency across a number of aspects of PHP). For others it wasn't an issue, which is why a pragmatic solution is the best that could be hoped for, not everyone would agree/like the outcome whatever was done (or not done). I can't see any other way of taking the language forward whilst causing minimum impact to users, which is why I (not you) think it was the most pragmatic way.
Every piece of code we write is "implementation-defined", including the bugs. It wasn't coherent with most other function implementations. Users couldn't reliably treat functions in the same way. I agree it wasn't coherent with numerical operations, but to get that consistency you would have to change a whole load more functions, and you would get many more complaints like this one.
"For all intents and purposes" - I think this discussion (and the many others that have featured on HN talking about similar issues of the weakly typed nature of PHP, such as == vs === ) show that it there are real world consequences to treating strings and numbers as compatible.
Not to mention being able to rule out large classes of errors at compile time, and ease of refactoring large code bases. You mean I get all that for free? Where do I sign up?
Obligatory language argument: If by ease of refactoring you mean having to change everything whenever anything changes just to avoid a little messiness. :)
It sounds pretty, but I'm not convinced this is a sound analogy. I think the walls are elastic to some extent. The real limitation on how much you can learn is not storage space, but time spent "moving furniture". You only have so much time to spend learning things, and you have to choose where to allocate it.