Why is this relevant? Why do we as programmers want to know about pure functional programming? What are its advantages? What's the point? This seems to add complexity. Etc.
I know there are good answers to these, but this intro has done little more than whet my appetite a bit...
Simplicity is hard -- and pure functional programming is a lot about simplicity, which does make it hard -- hard to learn, and hard to figure out how to tackle various problems.
But the simplicity has many rewards. Mathematical simplicity makes a lot of mathematical deductions tractable -- this is what is typically referred to as "ease of reasoning" about code.
Referential transparency adds a whole lot of ease to the reasoning process.
The pure functional approach also means that type safety goes much further. If you forget to hook up your functions together properly (forget an input, ignore an output) you're likely to get warnings/errors. In the imperative approach, if you forget a side-effecting statement that adds another input to some code, the compiler cannot help you.
Imagine testing -- imperative code requires tests to build up a mock world as input for the code, and then inspect the mock world that results as an output from the code.
Testing a referentially transparent function requires just calling it with differing inputs. It makes property-testing possible, too!
Imagine composition -- pure function composition of two functions composes the meanings of those functions. If those two functions work, so will the composed one.
Try to combine two pieces of imperative code -- that's not necessarily true at all, one might mutate data that's in use by the other. Aliasing issues may arise, etc.
So functional code is easier to reason about, more composable, easier to test, and gets more safety from type checking. It is harder to learn to use, and harder to figure out how to use it to solve certain problems. With time, however, more and more problems yield to the pure functional programming approaches.
An equivalent implementation with while loops, if conditions, continues, and breaks are usually harder to design correctly than a good recursive function.
Functional programming encourages use of small simple datatypes. Tuples instead of small structs. Lists instead of more complex container types. First-class functions instead of classes.
However, IMO 'purity' is a bit of a buzzword when applied to functional programming. You may disagree, but that's how I feel about it..
Here's one of my favorite examples. Say we have a set S and an element x, as in the following code:
"let S = Set.empty () in let S = Set.add S x in f (); if (Set.mem S x) then..."
If our code is purely functional, then it's impossible that x is no longer in S after our call "f ()". However, if we're using mutability, then maybe in our function f, we remove x from S. If that's the case, we really can't be sure what will happen when we reach our if-statement.
However, for me, the real realization was this combined with the fact that these languages also manage to be more expressive than the imperative ones I was using before. This might seem a bit counter-intuitive--after all, it feels like they give you less power, not more--but it has been the main draw to FP for me.
So the code is simpler, there is less to worry about and it's more expressive. What not to like?
Here's a famous post from HN's nostrademons that talks a bit about why people care about FP. https://news.ycombinator.com/item?id=185153
Without understanding functional programming, you can't invent
MapReduce, the algorithm that makes Google so massively scalable.
The terms Map and Reduce come from Lisp and functional
programming. MapReduce is, in retrospect, obvious to anyone who
remembers from their 6.001-equivalent programming class that
purely functional programs have no side effects and are thus trivially
parallelizable.
Longer answer: http://www.joelonsoftware.com/items/2006/08/01.htmlThe most powerful part about pure functional programming is that you get more powerful functions. Because your functions don't change the state of data, you can confidently combine them into new functions, producing a sort of chain effect. This can lead to very concise programs since there is no need to hold intermediate variables (i, count, temp, ...) in some place. What you sometimes end up with are one liners that -- if the functions are named well enough -- explain the entire logic of the program.
There are certain problems that lend themselves well to the functional style, mainly those where you are piping a piece of data through various functions and applying different transformations to it. It's worth learning at least a couple of functional languages so you're not applying a hammer where you need a wrench.
I don't quite understand this - how does this fit into the 'immutability' of fp? So functions can mutate data that goes into them, but they can't maintain internal state?
http://www.cs.utexas.edu/users/novak/gclwin.html
check out a few Lisp tutorials on Youtube and you good to go. Dont try to apply fuctionnal principles to procedural languages , if you are a beginner.
Using Lisp will force you to do and understand functionnal programming. And frankly , Lisp is a lot of fun and easy to start with. Dont be afraid by all these nasty (()) and weird (+ 4 5) operations , it will make sense quite fast.
something like
(defun add(a b)
(+ a b))
(add 4 5)
is actually easy to understand , isnt it ?They aren't as ugly as XML ;)
This was a great read convincing me so: http://www.defmacro.org/ramblings/lisp.html
I prefer: (defun add(a b) (+ a b))
Over: <defun name="add"><params><param>a</param><param>b</param></params> <+><a></a><b></b></+></defun> (Or some variant thereof)
Any day. The article above improved my understanding and appreciation of Lisp(s) but it made me dislike Java even more than what I already had!
-- Curried and uncurried add in Haskell:
curriedAdd :: Int -> Int -> Int
curriedAdd x y = x + y
uncurriedAdd :: (Int, Int) -> Int
uncurriedAdd (x, y) = x + y
;; Curried and uncurried add in Scheme:
(define (curried-add x)
(lambda (y) (+ x y)))
(define (uncurried-add x y)
(+ x y))
Haskell chooses to make curried the default, but allows you to write uncurried functions if you'd like. Lisp chooses the opposite.function g(h) { return function(y) { return h(h(y)); }; }
81 === g(function(x) { return x * x; })(3);
Specifically, why is this allowed and where can I go read about it?
return h(h(y));
- That you can use the name of a variable, h, as if it was a function? That's because Javascript has first class functions [1] - the language is defined to support passing them around as variables and calling them like that.
- That you can use h at all even though it's neither a local variable nor a parameter of the anonymous function? That's because functions in javascript aren't simply procedures in the traditional sense - i.e. description (function signature) + code - they are also closures [2]. If you declare one function inside another, it can capture (have a reference to) variables and parameters of the outer one. You are also guaranteed that local variables and parameters will not get cleaned up while a closure still exists that holds a reference to them.
[1] : http://en.wikipedia.org/wiki/First_class_function
[2] : Can't vouch for any particular article, try googling Javascript closures
So, in Javascript, variables can be functions. Which means you can pass in a function as a variable to another function. And the part that says h(h(y)), basically says that "h" has to be a function. Which means you pass in a function, and then it get's applied to itself in the way specified within that function, "g".
Another odd part is the function you pass in:
g(function(x) {
return x * x;
})(3);
because you are passing in a function, but I'd assumed that if you can only pass in one variable, and that variable has to be a function, then it seemed like you wouldn't be able to pass in an initial value for the function you want to apply. But I guess in Javascript you can pass in a value for an anonymous function defined inside a function call by using this syntax: g(function(x) {
whatever it is that happens in this function;
})(some_value_to_be_passed_into_the_previously_defined_anonymous_function); function callTwice(aFunction) {
return function(y) {
return aFunction(aFunction(y));
};
}
function square(x) { return x*x; }
var squareTwice = callTwice(square);
81 === squareTwice(3);Also, the names you gave don't help at all, as the idea of calling those g and h is to treat them anonymously. By calling it "callTwice", you are thinking about it as some sort of utility function, which is not the case. Shows you didn't grasped the idea behind it yet.
Currying allows functions to be broken apart ("specialized") on certain arguments for virtually free because specialization and normal function application, in effect, become the same thing.
Consider Haskell's _map_ function for example:
map :: (a -> b) -> [a] -> b
You can specialize it into a function that adds one to every element in a list by simply applying it to its first argument: incList = map (+1)
Currying also reduces the cost of combining functions by allowing any function that returns a function to have the returned function applied to any following arguments directly, without need of intervening syntax. For example, _flip_ modifies a function of two arguments (or more, thanks to currying) to receive its first two arguments in "flipped" order, the second first and the first second: flip :: (a -> b -> c) -> (b -> a -> c)
To flip _map_'s arguments, I don't need to write let flipMap = flip map in flipMap [1,2,3] (+1)
but, thanks to currying, can simply write flip map [1,2,3] (+1)
The value of these tools, however, is not to be able to write complete calls like those in my examples above but to quickly assemble from simple functions the exact functions needed to solve the problems at hand, usually by feeding those functions into the higher-order functions found in libraries.In sum, currying makes some of the most frequently done things in functional programming virtually free.
Here's a small example:
map (+ 3) [1, 2, 3] == [4, 5, 6]
f = (x) -> (y) -> x + y
g = f 6 f = \x -> \y -> x + y
g = f 6
with the added bonus of automatic documentation ghci> :t f
f :: Integer -> Integer -> Integer
ghci> :t g
g :: Integer -> Integer
ghci> :t uncurry f
uncurry f :: (Integer, Integer) -> Integer f = \x y -> x + y
and you'll have an implicit lambda before the y.That said. Looks like they hold your slides hostage if you don't pay. Scary.
I have a habit of assuming bad faith whenever money is involved, but looking at your pricing information, you're really just charging for a service...
and oh god, look at that mark up.
<section data-markdown>
<script type="text/template">
## Markdown support
For those of you who like that sort of thing.
Instructions and a bit more info available [here]
(https://github.com/hakimel/reveal.js#markdown).
```
<section data-markdown>
## Markdown support
For those of you who like that sort of thing.
Instructions and a bit more info available [here]
(https://github.com/hakimel/reveal.js#markdown).
</section>
```
</script>
</section>
That's cool.function g(x) { return function(y) { return x + y; }; }
f(1, 2) === g(1)(2);
How does this work? Since the function g is itself also returning a function, the call g(x) is itself literally another function address (if you will) awaiting an additional parameter with an invisible (y) on the end.
I have been dabbling in functional programming for a short while now, but this one took me completely by surprise. I had no idea JS would pass a function like that.
var g = function(x){
var f = function(y){
return x + y;
}
return f;
}
Also because of the magic of Lexical Scoping, the new function f holds onto a reference to the variable x that it saw when it was created. If you run var myfunction = g(5), you effectively get this: var myfunction = function(y) { return 5 + y }so why is there a limitation of just one argument? since lambda expressions can receive multiple arguments, and simply resolve them in order, why can't functional programming do the same? is this just a stylistic thing?
One of the neat things you learn if you start playing with lambda expressions in languages with algebraic data types is that multiple argument functions are modeled perfectly as functions which take single, tuple-typed arguments.
f :: (Int, Int) -> Int
f = \(a, b) -> a + b
ghci> :t curry f
curry f :: Int -> Int -> Int
ghci> f(3,2)
5
So, if you let your lambdas be as simple as possible then you naturally get "multi-argument lambdas" as the combination of tuples and lambdas.I think lambda functions is the only truly FP feature Javascript provides, but it's so darn useful that it really should be emphasized. Lately, I can't stand writing in languages that don't provide lambda functions (like PHP pre-5.3, or current Java), so at least Javascript has that going for it.
In FP, there is no difference between a Function and a Value. A function can be defined without a name. You can say every thing is a function & a function takes an input and after performing its magic (calculations), it must return you an output. All values are also functions. So technically there is no difference between x = 2 and x = function(){....}.
Now when you realize that all values are also functions or all functions are also values, you can pass functions inside other functions. Typically in imperative programming your functions only accepts values (like integers, strings etc.) and returns you values. But in FP you can pass functions inside other functions and you can return functions from functions.
Lets define a function doSomething(input){ return input } . Now you can call it by passing x where x could be a value or a function.
y = doSomething(x)
Now if x = function(){ ..} or x = 2, it really doesn't matter for doSomething because doSomething crunches an input and returns it.
By learning this technique, you can do lot of "interesting things". And Currying is one of those "interesting things". Every thing in FP really boils down to functions/values. 5 mins are over now.
var x = function(a,b,c){ return a - b * c };
var y = function(a,b) { return x(a, b, 5) };
Also, currying is married to positional arguments. What if you're trying to use keyword arguments? Can you curry this? var x = function(params) {
return params.top - params.bottom;
}