1,657 karma · joined September 8, 2018
The latter technically doesn't prevent anyone making money off it, but in practice it does (other than nominal fees).
That alone is a massive difference.
Also, a sibling poster mentioned ZIO/Scala which does the Structured Concurrency thing out of the box.
It's ultimately still driven my matching "random" identifiers (classes, ids, etc.) across semantic boundaries. Usually, the problem is that the result is mostly visual which makes it disproportionately hard to actually do tests for CSS and make sure you don't break random stuff if you change a tiny thing in your CSS.
For old farts like me: It's like the Aspect-Oriented Programming days of Java, but you can't really do meaningful tests. (Not that you could do 'negative' testing well in AOP, but even positive testing is annoyingly difficult with CSS.)
EDIT: Just to add. It's an actually difficult problem, but I consider the "separate presentation from content" idea a bit of a Windmill of sorts. There will always be interplay and an artificial separation will lead to ... awkward compromises and friction.
(And similar, it's just that images sprang to mind.)
"You want many folds!" We gottem!
Anyway, the larger point is that a re-entrant general solution is desirable. The sort example might be a bit misguided, because who calls sort-inside-sort[0]? Nobody, realistically, but these types of issues are prevalent in the "how to do closures" area... and In C every API does it slightly differently, even if they're even aware of the issues.
[0] Because there's no community that likes nitpicking like the C (or C++) community. I considered preempting that objection :). C++ has solved this, so there's that.
Not that you couldn't do source level analysis as you suggest... it just wouldn't be effective in many cases.
It would also be 'unstable' in the sense that it might depend on architecture, etc.
(You could solve that with a manually maintained stack for the context in a thread local, but you'd have to do that case-by-case)
It's infuriating when a type error can "jump" across global functions just because you weren't clear about what types those functions should have had, even if those types are very abstract. So early adopters learned to sprinkle in type annotations at certain points until they discovered that the top-level was a good place. In OCaml this pain is somewhat lessened when you use module interface files, but without that... it's pain.
In Haskell-land: At the global scope, yes, that's considered good practice, especially if the function is exported from a module. When you just want a local helper function for some tail-recursive fun it's a bit of extra ceremony for little benefit.
(... but for Rust specifically local functions are not really a big thing, so... In Scala it can be a bit annoying, but the ol' subtyping inference undecidability thing rears its ugly head there, so there's that...)
An argument can be made that it was instrumental in bootstrapping the early Internet, but it's not really necessary these days. People should know what they're doing 35+ years on.
It is usually better to just state fully formally up front what is acceptable and reject anything else out of hand. Of course some stuff does need dynamic checks, e.g. ACLs and such, but that's fine... rejecting "iffy" input before we get to that stage doesn't interfere with that.
We'll see once better non-cli UX appears. I'm low-key excited for what could be possible in this space.
IIRC Ocaml always compiles everything from source which has its advantages, but even that is a can of worms. (And sometimes binary compatibility can actually be easier, see e.g. Scala.)
[0] Well, plus git-mediate for solving conflicts
And, hey, if it works for you, that's great... but Batteries Included can also be great for a language.
As long as the 'effects' work will let me distinguish pure/non-pure, I'd be happy to use just that bit and stick with ZIO/TypeLevel's ecosystem... which will probably be supported forever, regardless of whatever happens with the "effects" stuff.
While React technically uses some OOP, in practice it's a pretty non-OOP way do UI. Same with e.g. ImGUI (C++), Clay (C). I suppose for the React case there's still an OOP thing called the DOM underneath, but that's pretty abstracted.
In practice most of the useful parts of OOP can be done with a "bag/record of functions". (Though not all. OCaml has some interesting stuff wrt. the FP+OOP combo which hasn't been done elsewhere, but that may just be because it wasn't ultimately all that useful.)