IMO the biggest win from functional programming is referential transparency. Automated verification (i.e. type checking) can definitely be useful on larger projects with bigger teams since it’s self documenting. That’s just my personal take on it though - there’s plenty for everyone to like.
Clojure has protocols which are probably inspired by type classes. Just like Clojure's protocols, type classes are a mechanism for ad hoc polymorphism that allows decoupling between data and the functions operating on that data.
Clojure indeed doesn't have monads, but this has to do with Clojure's culture (like all LISPs) of using macros for describing APIs for composing stuff. But those APIs aren't unified and some of the DSLs I've seen do not have a theoretical foundation, which really means they aren't reusable and some of them are flawed.
Due to its evolution and backwards compatibility concerns, some of its design shows its age as well. You can't make operations like "map" work on your own data types because it doesn't have a protocol defined for it.
Don't get me wrong, I actually like Clojure, but that the community is not using types like monads to drive their design is a flaw.
If you meant doesn't have the Maybe monad built in... why would you want that tangled up in your data? [2]
[1] https://github.com/khinsen/monads-in-clojure/blob/master/PART1.md
[2] https://youtu.be/2V1FtfBDsLU?t=2381If you want a more typical functional language without type declarations or monads, there's SASL. It's an ancestor of Haskell, but I don't know of any implementation which runs on modern hardware. Interestingly, SASL was once used to write an operating system.
What Lisp is really missing from an FP perspective is purity. In fact, maybe a pure variant of Lisp would be perfect for teaching.
[0]: https://www.microsoft.com/en-us/research/publication/wearing...
How can you even teach what purity is, if it is enforced?
"Bad things could happen, take my word for it?"
Lisps, Erlangs, and APLs all have distinct takes on what it means to be "functional".
For example, J is dynamically typed, permits mutable state, and doesn't really have first-class functions in any meaningful way. But it definitely has a functional "feel" to it (easy to compose functions, almost all operations are side-effect free, etc).
If you want to point fingers, I would be more worried about the rampant "anti-intellectualism" going on in this industry, accumulated along with other social problems (other -isms) we are experiencing, like sexism or ageism.
Look, it's fine if you don't understand, it's fine if something is out of reach relative to your current knowledge. And most often than not, the teacher is the one doing a poor job at teaching. There's a big difference in results between good teachers and bad teachers, between good books and bad books, etc. And maybe you don't need the subject in question, maybe you're fine with writing dirty Python scripts, whatever.
But dismissing work of other people as "academic flubbery" is mean and counterproductive and you can't teach people good manners — they should have learned those in their first 7 years of their life.
I'm also not inclined to fight for every beginner, I'm only fighting for those with good manners and if you'd know me, you'd know that I have open source libraries released and that I'm helping users in my free time and at great personal sacrifice. I'm actually putting my time and money where my mouth is and I've never berated anybody for not knowing something, only for being disrespectful.
The disrespectful ones can go somewhere else. I'm fine with having small and focused communities btw, instead of a big and toxic one, because life is too short to take abuse from random folks on the Internet.
When bad ideas are dressed up in academic authority, well they often have a hard time outside of academia. That's what "too academic" means. That this could be another bad idea dressed in academic authority and we'd have no way to tell.
I would really like to know why you conclude this, because it seems almost certainly wrong. SQL is a great example of a mainstream non-imperative, no-implicit-side-effect language, which is really the essence of functional programming.
That said, it is largely used in a giant procedural way most of the time, and is certainly not an ideal functional language, but the fundamentals of things like, map, filter, reduce, sort, etc. are there.
This is a very limited form of composition. It's very difficult to break a query down into a bunch of subcomponents that can be reused among groups of queries. CTEs are close, but it's really hard to achieve re-usability of a CTE unless you are stitching together strings at runtime.
Probably the closest you could get is a view, but even then if you have many views stitched together to form a query this can impact performance in ugly ways.
Generally in order to achieve the best performance and to get the most of out of the DB engine it seems like producing unique SQL for each query which is optimized for that query is generally the optimal approach.
In summary: Just because SQL is based on a few composable operations (map, filter), does not mean it is composable itself.
There are a few that are good at optimization (and in my limited experience, Haskell is one of them), but in general if you use lots of conceptually clean maps and filters, you will occasionally see cases where your performance is very bad because you don't have full control over exactly what is evaluated when, won't you? That seems like basically the same problem that you have with using views and not trusting your query planner to do things efficiently.
>> "up its own butt about monads and type classes and algebraic data types"
Well, those are some of the best things about doing functional programming in languages that can afford them.
>> "I essentially wrote the whole thing off as academic flubbery"
And maybe it was your attitude to the whole thing.
>> "It wasn't until years later and exposure to .NET LINQ that it started to click..."
So seriously, can't you find anything else that changed "years later"? Haven't you changed? Aren't we talking about years of accumulated experience?
Also, .NET LINQ might be a cool example of what you can do with FP, there are elements of FP in it, certainly that's a monadic interface that makes it tick. But filtering an IEnumerable or an IQueryable is as interesting as executing an SQL query.
What have you learned about FP from executing SQL queries? Probably nothing.
Just saying.