6 ms·
Kool-Aid-free answer: "Functional programming" can mean one of three things. 1. Higher-order programming: the use of higher-order functions to make code more
by rkts 17y ago
Kool-Aid-free answer:
"Functional programming" can mean one of three things.
1. Higher-order programming: the use of higher-order functions to make code more general/compact. Since you know Ruby, you're already doing some higher-order programming, but you may not understand it well enough to take full advantage of it. The best way to learn higher-order programming is to read SICP.
2. The use of immutable (aka persistent, nondestructive) data structures, i.e. data structures that can be updated without mutation. For example, linked lists allow you to prepend an element without changing the original list. This makes code cleaner in some cases and has advantages for concurrency. For specifics, look up Clojure.
3. Functional purity, aka referential transparency: the property that, for any input x, a function must always produce the same output x'. That is, all functions must be functions in the mathematical sense of the word. In practice, this doesn't really mean eliminating impure functions, but rather partitioning your program into "provably pure functions" and "possibly impure functions," using a clever hack (monads) to ensure that the output of possibly-impure functions is invisible to the provably-pure ones.
So, supposing you had a pure function whose behavior you wanted to randomize, you couldn't just throw in a call to the random() function, but would also have to convert it and all the functions that depend on it into impure (monadic) functions, replacing all function calls with the bind operator (>>=). It's quite complicated and I have never found a reason to believe it's a good idea, other than some theoretical stuff about "safety" and compiler optimizations that make your program 2% faster. I suggest not wasting your time on it.
- blasdel 17y agoYou don't understand monads very well, they are orthogonal to 'impurity', and don't even necessarily involve state or sequencing at all. A more straightforward way to describe how you do random() is that your function takes the randomness as an argument. Functions that take input take IO as an argument, and those that produce output return IO in some form. You don't even have to mention the dreaded word.
- rkts 17y agomonads... don't even necessarily involve state or sequencing at all I never said that they do.
- blasdel 17y agoYou used the word "impurity". What other meaning did you intend?
- rkts 17y agoConsider the getLine function: getLine :: IO String getLine takes nothing as its input--not the state of the world, or whatever, but nothing--and produces a string that's inside an IO monad. To all appearances, it's an impure function. But because the String is inside a box (so to speak) you can't peek at it--instead, you can only give it to another function, provided that function also returns a box you can't peek into. In effect, this creates two classes of functions. Some, like getLine, can have side effects, generate random values, look into other boxes, whatever. These are technically "pure" in a mathematical sense since their outputs are always inside identical boxes, but in practice they behave just like impure functions, and you reason about them the same way. The rest have more restricted capabilities, and because their values aren't inside boxes, the compiler can verify that they return distinct values in a pure manner. So, for an extreme example, consider this function: foo (x) { x++; return x; } In Haskell foo would return "IO Int," which means the "Int" may be produced impurely. Actually, the integer is produced in a pure manner, so it would be fine for foo to return a plain Int. But the way Haskell determines purity is too crude to figure that out: all it knows is that foo depends on a mutation, which may make the output impure. Impurity is contagious, so foo "catches" it from ++ and thus has to put its output in a box. Hence, the typical description of pure functional programming as "functions only transform inputs to outputs" is only true in the most trivial mathematical sense, and has no practical import. Pure functional programming really means writing a crude proof that a certain subset of your program is pure, and the compiler checking the proof for you. (Disclaimer: I understand that this is a very vague high-level description of monads, that monads can work in other ways and do many other things, and that purely functional languages can handle state/side effects/etc. in other ways. It's a complex issue and I'm just trying to convey the way that it usually works in practice.)
- deleted 17y ago[deleted]