3 ms·
Functional programming makes compilers nicer to work with, because you can tell them explicitly when locality can be assumed. All compilers which do any kind o
by msla 9y ago
Functional programming makes compilers nicer to work with, because you can tell them explicitly when locality can be assumed.
All compilers which do any kind of optimization have to reason about the code as if it were functional. Otherwise, they couldn't rearrange mathematical expressions and do things like common subexpression elimination or constant folding or even simple algebraic rearrangements we expect to happen because we, as humans, know that mathematical operators are are functions and therefore side-effect-free and therefore can be switched around arbitrarily as long as the end result is correct, because the end result is all that matters.
But a compiler which could only optimize arithmetical and algebraic code would be worthless. How about memory accesses? How about function calls in tight loops? And that's where you run into problems in a language like C, where strong assumptions about who gets to look at what generally don't hold. Optimizing memory accesses is hard because you don't know who's looking at the memory in a global sense. Spooky action-at-a-distance crops up, the kinds of things humans don't cope with well because the effect could be many pages of code removed from the cause. C has the volatile keyword for some instances of this, which basically kills optimizations for certain variables, but the general problem stands: C is unphysical. Locality cannot be assumed. Humans don't deal with that very well.
In a language like C, therefore, there's a tension between generating optimized code and generating predictable code, and that tension comes from the fact the compiler doesn't know which code could have side-effects and, therefore, invoke spooky action-at-a-distance if it's optimized too aggressively.
In Haskell, or any other language where side-effects must be explicitly marked, that problem goes away. Most code is purely local in its effects, and only special code, written inside a special monad, can invoke nasal demons if the optimizer gets too frisky. The compiler can trace its data-flow graphs and do all kinds of tricks secure in the knowledge that nobody outside can peek in to see how the sausage is being made. Only in special, marked locations do the values get exposed to the outside world, which must be done in an orderly fashion.
So all code is potentially functional. Functional languages just make it possible for the developer and the compiler to agree about precisely which code that is.
- benlorenzetti 9y ago> ...Optimizing memory accesses is hard because you don't know who's looking at the memory in a global sense...In a language like C, therefore, there's a tension between generating optimized code and generating predictable code, and that tension comes from the fact the compiler doesn't know which code could have side-effects and, therefore, invoke spooky action-at-a-distance if it's optimized too aggressively. I get this argument for functional languages and Haoyi's description for functional style, by writing down the expression tree not just one possible serialization the expression tree, was excellent); both the freedom to access memory and the lack of richer information about possible execution orders makes it more difficult for automatic compiler optimizations. I have definitely bought into writing C in a functional way when using local variables. However, the lack of some compiler optimizations due to memory aliasing guarantees is not always a disadvantage. Like bootstrapping a compiler, taking advantage of new processor features, doing an inherently sequential task like state machine parsing, or even if you just enjoy thinking about data and algorithms at a low level. What imperative languages need to remain competitive is richer type systems regarding objects with pointers into the heap. And this is no secret; languages have been experimenting with this forever. C++'s attempt with object oriented programming was a good stab in the dark but clearly has limitations, with the explosion of type information regarding things like exceptions and wart covers like move semantics. What I would like to see is a language with weak typing and free pointers like C, but with a more capable, generic type system with concepts, like that described by Alexander Stepanov in Elements of Programming. Also object orientation as a language feature should be replaced by [some syntactic sugar + generic functions + function overloading + linearish? types] to make OO style easier than it is in C. Things like memory aliasing optimizations would be managed by generic functions and type concepts provided by STL like libraries. Perhaps it makes me a slower, less productive programmer but I like imperative programming and access to memory. That is the part I enjoy.
- msla 9y agoI fully agree that there's a time and place for explicitly sequential code. I just think that it's safer for everyone if it's explicitly marked as being sequential, so compilers know that most optimizations are now off-limits.
- benlorenzetti 9y agoThis seems like a reasonable compromise if people are interested in a language that can do both. Using C's syntax, a language could modify the semantics of terminators , ; : to indicate strict/total ordering of statements.