Not really. He suggests that if a function is called from multiple places, one should try to make it pure to avoid subtle bugs. If called from a single place it may be better to inline it.
Citation: "I don’t think that purely functional programming writ large is a pragmatic development plan, because it makes for very obscure code and spectacular inefficiencies, but if a function only references a piece or two of global state, it is probably wise to consider passing it in as a variable."
His 2014 thoughts:
No matter what language you work in, programming in a functional style provides benefits. You should do it whenever it is convenient, and you should think hard about the decision when it isn't convenient.
Which is still a very different statement from the way functional zealots would put it.
Carmack's talking about pure functions at the architecture/design level. Within those functions, there's still lots of temporary mutable state, I'd be willing to bet. He's writing graphics code, he's probably not passing functions to functions in order to sum an array, he'll just do the fast, iterative thing.
I'm not going to do the whole spiel about performance, but I know a lot of FPers who wouldn't care about the implementation of map, so long as the external contracts are kept.
The beauty of functional programming is that it doesn't matter how map works. So you can make map work as fast as possible through all the techniques you want, since code can't rely on the behaviour. Only on the input.
Interfaces you supply will necessarily constrain implementation details. So it winds up mattering.
Passing a function to a function is a bunch of indirection and extra stack frames(!) compared to updating very small, memory aligned mutable state in-line with the work you're doing. It's even worse with closures where you're creating anonymous data structures and passing them around. You can read up on TLBs and the speed difference between L1 cache and main memory if you'd like to know more.
You might not care about the above if it's more 'beautiful' to you, but it's vastly, vastly less performant.
The old school of algorithm developers used to introduce hard, explicitly verified preconditions and postconditions. Typically this is done in C and C++ using assertions.
In general, any dependence on external mutable state should be asserted or otherwise verified. Those checks can be disabled for performance later. Meshes very well with actual tests too.
Citation: "I don’t think that purely functional programming writ large is a pragmatic development plan, because it makes for very obscure code and spectacular inefficiencies, but if a function only references a piece or two of global state, it is probably wise to consider passing it in as a variable."