That would only work if the new versions were willing to break backward compatibility. The safety (and correctness) of a language is not about what it can do, but what it cannot.
Because that built habits. Has large bodies of education and documentation around it, and often even tooling (like snippets, ai completion, linters, static analysis)
100%, I used to joke the reason for this is its the "nobody got fired for buying IBM" color system.
#1 it takes the most modern widely accepted space in color science, CAM16 for hue and colorfulness. CAM16 is relatively incredibly complex, about 500 lines of code.
#2 it maps it to L*.
#1 is because nobody gets fired for basing Google's color system on CAM16.
#2 is for WCAG.
There was continually interesting conversations on what exactly the name of the space was and whether it represented a new color space that precluded more formalization of it, the code ended up being the spec as it were. I did get a blog post out: https://material.io/blog/science-of-color-design
I don't think passing state through functions calls add cognitive load: it just make it visible. Global state has the same cognitive load, except hidden.
If a state is passed through dozens of function calls, this may indicate that it is shared by too many parts of the code, or that it is managed at the wrong layer of the architecture. When using global state, these potential problems are difficult to spot.
It's more complicated than that. The study referenced in the book found that snake_case makes variables easier to read, but the whole program harder to parse (my guess is it's because of the visual similarity between the underscore and a space). With camelCase, it's the other way around.
I vote for kebab-case, but I didn't find any study where it was included...
In order to know "what changed", you need at the very minimum to maintain a meta-state about your application state.
In most retained-mode GUIs, this meta-state is often a copy of a significant portion of your application state, but with a very different structure. To maintain the integrity of both copies, you then need a layer of events and/or listeners on top of that, with a complex and dynamic control flow.
Retained mode optimizes for display throughput, which matters a few decades ago. Immediate mode is better for latency and consistency, which are much more important now.
I believe the way it's usually done is to always parse a tuple, then parse the arrow as a binary operator applied to the two surrounding expressions. This potentially produce a syntactically incorrect AST (e.g. if there is an arrow following a tuple containing numbers), so you need to detect those in another pass and produce the corresponding error.
Can be done in one go: just check the type of the left and right operand at the end of X -> expr "=>" expr, or assign "=>" the highest priority when following a tuple, X -> tuple ("=>" "{" body "}")?.
https://dev.epicgames.com/documentation/en-us/uefn/specifier...
It's a compromise between the granularity of correctness checks and readability, but IMHO it's still a big improvement over current type systems.