When it comes to expressing logic in small composable, understandable pieces, nothing else can compete.
Unfortunately, it does have the challenges listed in the OP, so it seems to make most sense where either (a) it is ok to leave performance on the table in the interest of clarity or (b) you create a little sandbox in which you use functional programming for clarity, and something outside your sandbox compensates for the performance cost.
React and Om are examples of (b). They let you write pure functions that return the entire DOM. Then, outside that sandbox, a DOM differ makes it so you don't force the browser to re-render the entire DOM every time.
I think it's also interesting to note that sometimes when choosing immutability as the default, which gives a slight performance penalty for basic operations compared to doing normal mutation, you end up being able to save lots of performance on a larger level. React wrappers in ClojureScript, such as Om, are a good example of this - since data is immutable, shouldComponentUpdate is automatically and trivially implemented for you, leading to oftentimes better performance than straight React. I reckon this would also be the case with the lock-free code you write in Clojure, etc.
Unfortunately, it does have the challenges listed in the OP, so it seems to make most sense where either (a) it is ok to leave performance on the table in the interest of clarity or (b) you create a little sandbox in which you use functional programming for clarity, and something outside your sandbox compensates for the performance cost.
React and Om are examples of (b). They let you write pure functions that return the entire DOM. Then, outside that sandbox, a DOM differ makes it so you don't force the browser to re-render the entire DOM every time.