4 ms·
> First-class functions, lambdas, and closures are mostly unheard of in the top 20 programming languages A quick Google search tells me the "top 20" includes P
by deckard1 4y ago
> First-class functions, lambdas, and closures are mostly unheard of in the top 20 programming languages
A quick Google search tells me the "top 20" includes Python, JavaScript, Java, C#, C, Go, Swift, PHP possibly Ruby/Perl/Kotlin/etc. I can't think of a single one that doesn't have either first-class functions or some form of closures.
> Proper tail calls.
This is an optimization issue for most languages, and they have made the trade-off of keeping a stack trace vs. optimizing it away. Having it in the Scheme spec was incredibly contentious and caused many heated debates.
> none of them implement macros ergonomically.
I think this really depends on what you mean "ergonomically." That's a weasel word in this context. Because there are two camps. There is the CL Lisp-2 that feels they should be allowed to use LIST as a variable in a macro so they went and created a whole namespace just for functions but are perfectly fine with the ugly GENSYM hack. Then there is the Scheme camp that failed to come up with a suitable hygienic replacement for DEFMACRO for like 20 years. Macros have been broken in LISP world longer than most of us have been alive.
> React where you'll have huge config objects passed
Not sure what you're referring to here. A/B testing is a thing. Can't do that with macros. Hydration is also a thing, because of SSR. Maybe you're seeing that?
> REPL-driven development, type errors are almost non-existent in practice
ehhhh. No. And I say this as someone that generally prefers dynamic over static typing. You can easily have objects in your REPL that were the result of previous bugs and get your app in an inconsistent state. You either reload, or spend your entire life cleaning up memory and hoping you get it right. There is no silver bullet here, despite what others have commented on. Because you're talking about schema migrations here. Bad data structures have to be transformed to good data structures. Or you'll see bugs in the REPL that aren't actually bugs in the source. Keeping the REPL and source in sync is also tedious, to put it mildly.
Look into Erlang does and what is required to get live code swapping correct. It's a headache that is only worth it in very niche apps (like massive telecom systems). It doesn't make sense doing this during development. Much saner to just reload and start from a fresh, consistent point. Otherwise you will spend time hunting down bugs that do not exist outside your REPL.
- hajile 4y ago> A quick Google search tells me the "top 20" includes Python, JavaScript, Java, C#, C, Go, Swift, PHP possibly Ruby/Perl/Kotlin/etc. I can't think of a single one that doesn't have either first-class functions or some form of closures. Most of them don't have all of these features together and they often have incredibly bad versions of those features that are basically unusable. > This is an optimization issue for most languages, and they have made the trade-off of keeping a stack trace vs. optimizing it away. Having it in the Scheme spec was incredibly contentious and caused many heated debates. The JS stack already goes away the second you do anything asynchronous. As this is something you do frequently, stack traces are already incredibly short. Meanwhile, the alternative for the use cases of PTC is loops and I don't hear complaints that loops don't save your state. It's in the spec, it should be implemented. As to Scheme, you won't find anyone today arguing that PTC is bad. The bigger argument would be about how full continuations are a performance disaster. > I think this really depends on what you mean "ergonomically." Infix macro systems are terrible to use compared to S-expr macros and I don't think this is anywhere close to controversial. Can you point to a counter-example? The best infix example I know of is Dylan, but not only is that language barely infix (its S-expr foundations are very apparent) and they still just aren't as easy to use. > ehhhh. No. And I say this as someone that generally prefers dynamic over static typing. You can easily have objects in your REPL that were the result of previous bugs and get your app in an inconsistent state. You either reload, or spend your entire life cleaning up memory and hoping you get it right. There is no silver bullet here, despite what others have commented on. Because you're talking about schema migrations here. Bad data structures have to be transformed to good data structures. Or you'll see bugs in the REPL that aren't actually bugs in the source. Keeping the REPL and source in sync is also tedious, to put it mildly. How does this entire bit have anything to do with dynamic vs static typing? You could have a REPL with static typing if you truly wanted. In any case, reloading data from the code isn't that difficult and most data will be held in closures which means you can decide exactly how far up you want to replace local data (and if you're going about it smartly, you have created a few "mocks" to work with that can be used to refresh data). The absolute worst case (restarting the REPL) is what other languages would force you to do anyway which still means you have a lot to gain for most development and bugfixing and absolutely nothing to lose. As to data is held in a database, then you have all the same problems in other languages except that fixing these issues from the REPL is generally easier because you are already connected and ready to start fixing things. > Look into Erlang does and what is required to get live code swapping correct. BEAM is an amazing platform, but a REPL for development and live code swapping are two different discussions. Doing REPL work on production systems has a very big chance of catastrophic damage and I wouldn't recommend it.
- tonyg 4y ago> [Proper tail calls are] an optimization issue for most languages It's an optimization issue for no languages; it's an optimization issue for some language implementations. At the language level, it's a resource management (garbage retention) issue that leads to an expressiveness problem. See Clinger's papers on safety-for-space (e.g. [1]) and Felleisen's paper on expressiveness [2]. Support for proper tail calls in a language implementation also sometimes makes program execution faster, but that's not the main motivation. [1] https://www.cs.tufts.edu/~nr/cs257/archive/will-clinger/proper-tail-space.pdf https://www.cs.tufts.edu/~nr/cs257/archive/will-clinger/prop... [2] https://www.sciencedirect.com/science/article/pii/016764239190036W https://www.sciencedirect.com/science/article/pii/0167642391...