First, Cale pointed out that my expansion of
foldlwasn't exactly right. Actually, it was a valid expansion of
foldl. For the purposes of that discussion, I wanted to focus on the concept of left and right folds, not the specifics lazy vs. strict evaluation. If you look at the ghc library docs, you'll find over a dozen variations on the theme of a "fold".
Cale, as always, was prompt, elucidating, helpful and correct. Thanks, Cale!
A few readers also pointed out that my discussion of the power of closures didn't include a single closure. Funny, that. Strictly speaking, curried functions, anonymous functions and sections aren't closures per se. Although I was trying to explain closures, I wound up explaining higher order functions instead.
At one point, I thought about posting a pedantic rebuttal, but really, that doesn't help anyone. So let's call this a fair cop and move on.
Closures are like a gold pass -- if a language provides both first class functions and closures, then it enables higher order programming. Pascal offers neither, and I remember writing sort and search code for every little type I wrote in my data structures class. C, for example, doesn't quite provide first class functions, and it certainly doesn't provide closures. But C does provide function pointers, which can approximate higher order programming in certain limited scenarios. I remember how wonderful it felt when I realized that library functions like
bsearchmeant I didn't need to write (and debug) nearly as many sort and search functions anymore.
But I promised you a closure, so here's a function with a closure:
Or, more idiomatically:main = do out <- open "out.txt" WriteMode
mapM_ (\i -> hPutStrLn out $ show i) [1..10]
Interestingly, here's a different version of that same function that sends output to standard out. Note how similar this code is to the previous example:main = do out <- open "out.txt" WriteMode
mapM_ (hPutStrLn out . show) [1..10]
The key here isn't about functions that have bindings to their outer environments. It's about higher order programming. And I should have said that yesterday.main = mapM_ (putStrLn . show) [1..10]
Turns out that if you take some random programming language, add closures and first class functions, you can start to do some pretty amazing things.
Maybe the debate about adding closures to Java isn't really about adding closures to Java. Maybe it's about bringing higher order programming to Java, where the most vocal part of the debate involves complaining about the proposed syntax, or questioning the value making a large language definition even larger..