Regarding your uncertainties about functional programming in Embedded episode 138, I think the problem is that you're reading the Wikipedia page instead of jumping in and experiencing it. This gives you the math nerd / pure CS approach, which sets your head to spinning with lambdas and such. That's like teaching someone electronics by starting them out on Maxwell's equations instead of blinking an LED.
There's actually a whole spectrum of FP languages which spans a much wider gamut than the pure lambda calculus viewpoint of FP. I've written up a concise summary here:
http://stackoverflow.com/questions/2271417/is-erlang-really-a-functional-language/11111614#11111614
That's an answer to a question about Erlang, but it applies broadly to FP as a whole.
Notice that JavaScript -- a language both of you know, I believe -- is "functional" by my definition. In fact, JavaScript was originally created as a C++-flavored Scheme dialect. That's why you can say something like this in JavaScript:
var f = function(arg1, arg2) {
return function(arg3) {
// Do something with arg1, arg2, and arg3
};
};
That assigns a 2-parameter function to a variable, which you can call as f(a, b). When you do that, you get back a different function that takes one parameter, but which has arg1 and arg2 available to it because of a common feature of FP languages called closure. This is powerful stuff.
It might be clearer with a concrete example:
var animals = [
{ name: 'kangaroo',
weight: 110,
},
{ name: 'ox',
weight: 643,
},
{ name: 'mouse',
weight: 4,
},
];
var sorted = animals.sort(function(a, b) { return a.weight - b.weight });
That sorts the animals by weight. I didn't have to write a separate function and pass it in via a function pointer as with C's sort(), I just built a function value inline and passed it in.
Functions in JavaScript are *values*, not a distinct entity class from variables and objects. These values are of class Function and they have properties like any other JavaScript object. For example, the f function value above has f.length which is equal to the number of parameters the function expects, 2 in this case. If you say f().length instead, you get 1, since that's the length of the parameter list for the inner function.
For more surprising details on Function in JavaScript, see:
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function
I think the best way to learn functional JavaScript is to build a dynamic web app using jQuery. For example:
$("div.commentForm").mouseenter(function(event) {
alert("The mouse entered comment form ID " + event.target.id + "!");
});
In this example, the $ function returns a jQuery object containing a list of matching objects to which we attach an event handler. Function call chains, applications of functions to lists of objects, and inline function values (a.k.a. lambdas) are all FP concepts.
A less pure FP language which you both know is Python. I've done very little with Python, but when I typed "Functional Python" in to Amazon, I got a book by the same title. Maybe you will enjoy it.
After you've programmed one of these languages in an FP style for a while, I recommend that you move on to either F# or OCaml. Like JavaScript, these are multiparadigm languages, so you can ease into FP while still doing imperative and OO programming where that is more comfortable. But unlike JavaScript or Python, values are immutable by default and FP is taken to a much deeper level.
For example, an if/else statement in F#/OCaml always returns a value. It actually works more like C's ternary operator than if/else in traditional imperative languages. But unlike C, when you need more than two branches the required nesting and chaining is generally a lot easier to read:
int x = someFunction(param1, param2) ? 42 : otherFunction(param3) ? 69 : 99;
versus:
let x = if someFunction(param1, param2) then
42
elseif otherFunction(param3) then
69
else
99
Notice that F# is whitespace-sensitive and doesn't have semicolon statement separators, much like Python. But to say the same thing in Python, you'd have to do it this way, because an if/elif/else statement doesn't have a value:
if someFunction(param1, param2):
x = 42
elif otherFunction(param3):
x = 69
else:
x = 99
Maybe that looks clearer to you, but there are problems. First, you've repeated the variable name three times, a violation of the DRY principle. Second, there's nothing forcing you to return a value from all three branches, so you could miss one in a more complicated bit of code, leaving x undefined. There's no such thing as an undefined value in a strong FP language like F#. (And thus, no null or uninitialized pointer dereferences!)
Getting back to my F# example above, x is a read-only value, not a variable, and it is equal to the value of the last statement in each branch. (We're just returning a simple integer in the example, but it could be code of any complexity.)
By refusing to let you have a dangling "else" branch, F# closes off a whole class of programming errors. (Well, there are cases where "else" is not required, but chasing such details will send us off into the weeds.)
I wrote a long post about why I like F# here: http://goo.gl/0yfTfR
Because F# is a .NET language, you can use it anywhere you can use VB.net or C#.
F# is also portable to non-Windows systems via Mono. I've used it on Linux and Mac OS X, even doing nontrivial things like UDP multicast networking code in it.
You might prefer OCaml to F# when:
- you need native compiled binaries rather than .NET IL code;
- you can't accept use of the .NET or Mono runtime; or
- you're anti-Microsoft
Outside of those cases, I prefer F#. It's like OCaml with all the ugly bits sanded off. :)
By all means, stay away from Haskell and Lisp. That's the pure CS nerds off doing their thing. Erlang and the ML family are far more practical languages for practitioners like ourselves.
I'm told that Scala fills that role for JVM users, but I couldn't say from personal experience.
Apple's new Swift programming language also has quite a lot of the FP nature to it.
Comments