> I think functional programming is really good at some things, I don't feel like many people talk about the things it's not good at.
This is a wonderful tenet in general: let's think about what X is bad at, rather than what it's good for.
While I'm not much of a Rubyist (I've hacked a little in my time, but I fall on the Python side of the divide), working with trees (hashes of hashes are a kind of tree) has never been easier than in Clojure in my experience. I suspect this is true of any lisp.
Could you expand on how Clojure makes it easier to deal with the frustrations your parent comment mentions (deep merges, shared reliance on hash structure, reproduced logic, and handling of optional values)? I've only used Clojure a bit, but I'm not sure how it solves any of these problems (which I also find frustrating in Ruby).
Persistent data structures are part of it, for sure. But on a higher level. On a lower level, if you look at how and assoc-in works in Clojure, the scales will fall from your eyes (they certainly fell from mine). Consider:
(def g {:x "a" :y {:k 71}})
user=> (assoc-in g [:y :k] 72)
{:y {:k 72}, :x "a"}
With this you can walk and mod deeply nested datastructures with ease (and others can reason about it well).
I may be misunderstanding your point, but that's just a well-done function which could be written in virtually any language, the advantage isn't inherent to Clojure.
The difference is that in Clojure, `assoc-in` is effectively a deep copy as well since the data structures are immutable. Most of the complexity involved with nested maps is about the effects of modifying them. In practice, this doesn't exist in Clojure.
> which could be written in virtually any language
What natrius says is completely right on this point (which explains why those functions don't exist commonly outside of lisp) but it should by now make you wonder: if that's true, why haven't they?
This is a wonderful tenet in general: let's think about what X is bad at, rather than what it's good for.
While I'm not much of a Rubyist (I've hacked a little in my time, but I fall on the Python side of the divide), working with trees (hashes of hashes are a kind of tree) has never been easier than in Clojure in my experience. I suspect this is true of any lisp.