Without understanding functional programming, you can’t invent MapReduce, the algorithm that makes Google so massively scalable.



interface IFromIAndI {

Integer call(Integer a, Integer b);

}



IFromIAndI add_two_integers = new IFromIAndI() {

public Integer call(final Integer a, final Integer b) {

return a + b;

}

};



add_two_integers = lambda { |a,b| a + b }



add_two_integers.call(35, 42);



add_two_integers.call(35, 42);



multiply_two_integers = lambda { |a,b| a * b }



DRY

adder_wth_acc = lambda { |acc, list|

if list.empty?

acc

else

adder_wth_acc.call(acc + list.first, list[1..-1]) # [1..-1] returns a copy of the list without the first element

end

}

adder = lambda { |list|

adder_wth_acc.call(0, list)

}

adder.call([1, 2, 3, 4, 5])



multiplier_with_acc = lambda { |acc, list|

if list.empty?

acc

else

multiplier_with_acc.call(acc * list.first, list[1..-1]) # [1..-1] returns a copy of the list without the first element

end

}

multiplier = lambda { |list|

multiplier_with_acc.call(1, list)

}

multiplier.call([1, 2, 3, 4, 5])



adder

multiplier

folder = lambda { |default_value, binary_function, list|

fold_with_acc = lambda { |acc, list|

if list.empty?

acc

else

fold_with_acc.call(binary_function.call(acc, list.first), list[1..-1])

end

}

fold_with_acc.call(default_value, list)

}



folder.call(0, add_two_integers, [1, 2, 3, 4, 5])

folder.call(1, multiply_two_integers, [1, 2, 3, 4, 5])



folder

folder.call(0, lambda { |a, b| a + b }, [1, 2, 3, 4, 5])

folder.call(1, lambda { |a, b| a * b }, [1, 2, 3, 4, 5])



folder

add_two_integers

multiply_two_integers

folder

IFromIAndI

getDefaultFoldValue

Visitor

[1, 2, 3, 4, 5]

[2, 4, 6, 8, 10]

fold_coder = lambda { |default_value, binary_function|

fold_with_acc = lambda { |acc, list|

if list.empty?

acc

else

fold_with_acc.call(binary_function.call(acc, list.first), list[1..-1])

end

}

lambda { |list|

fold_with_acc.call(default_value, list)

}

}



adder = fold_coder.call(0, lambda { |a, b| a + b })

adder.call([1, 2, 3, 4, 5])

adder.call([2, 4, 6, 8, 10])



Actually, there’s a far simpler way to avoid having to remember the default value when you want to fold over addition. But let’s just play along so that we don’t have to come up with an entirely new set of examples to demonstrate the value of functions as first-class values.



folder

curry = lambda { |fn,*a|

lambda { |*b|

fn.call(*(a + b))

}

}



plus_one = curry.call(add_two_integers, 1)

times_three = curry.call(multiply_two_integers, 3)



compose

carbnation

# fizzbuzz.rb



def compose *lambdas

if lambdas.empty?

lambda { nil }

elsif lambdas.size == 1

lambdas.first

else

lambda do |n|

lambdas.first.call(compose(*lambdas[1..-1]).call(n))

end

end

end



def carbonation(modulus, printable_form)

i = 0

lambda do |n|

(i = (i + 1) % modulus) == 0 && printable_form || n

end

end



print(((1..100).map &compose( carbonation(15, 'FizzBuzz'), carbonation(5, 'Buzz'), carbonation(3, 'Fizz'))).join(' '))





carbonation

Compose

folder

fold_with_acc

binary_function

fold_with_acc

binary_function

lambda { |list| fold_with_acc.call(default_value, list) }

default_value



I hope you’re convinced, by now, that programming languages with first-class functions let you find more opportunities for abstraction, which means your code is smaller, tighter, more reusable, and more scalable.



Further Reading





the

There has been a great deal of interest in closures lately, driven in great part by the fact that there is talk of adding some form of anonymous functions to the Java. Most of the time, people talk about “adding closures” to Java, and that prompts a flurry of questions of the form “what is a closure and why should I care?”The discussion around closures tends to go on and on about the “closing over” of free variables and only lightly touch on the biggest change to Java: functions as first-class objects with a lightweight syntax for creating them. Making it easy to do something basic like define a new function is more than just a little syntactic sugar: it makes it easy to do new things with functions that were impractical when you needed a lot of boilerplate to make anything work.I’m going to try to explain first class functions using Ruby (it is possible to write code that does exactly the same thing using the current Java feature set, however the result is so wordy that it obscures the basic idea being presented: call it accidental complexity, or perhaps yellow code .) Ruby is a good language for demonstrating features that ought to be in Java. Like Java, Ruby uses squiggly brace syntax. Like Java, everything in Ruby is an object—whoops, Java has primitives. Okay, like Java, functions are represented as objects.In Java you write:(The Java convention is to name things in lowerCamelCase , but we’ll ignore that. If you need to print this essay on a dot-matrix printer you may want to make some changes first.)In Ruby you write the function as:Later on, when you want to call your function in Java, you write:And if you like semicolons, you write the exact same thing in Ruby:You can do the same thing with multiplication:In the examples above, functions look a little like methods. The Java version is obviously implemented as a method. But what we did in both cases was assign the resulting function to a variable. In Java, assigning a method to a variable is not particularly easy (it is possible using reflection).Anything that can be assigned to a variable is a value. If it can also be passed as a parameter or returned from a method (or function), we say it is a first class value. Functions as first class values, or first class functions, are very interesting. For example, what can we do passing a function as a parameter to another function?Hmmm. Well, I am breaking a cardinal rule of selling something. We’re talking about shiny new toys without identifying a problem to be solved. Let’s talk about my favourite problem: writing the same thing more than once, violating theprinciple.Here are two pieces of similar Ruby code:And:What do they both do? Pretty much the same thing: they accumulate the result of some binary operation over a list of values.accumulates addition, andaccumulates multiplication. You could call this a “Design Pattern.” If you did that, you would use the exact chunk of code everywhere. I would call that retrograde. Didn’t our predecessors invent the subroutine so we could eliminate writing the exact same piece of code over and over again?Why can’t we do the same thing? Well, we can. A subroutine does the same thing over and over again, but it takes different parameters as it goes. What is different between adder and multiplier? Ah yes, the adding and multiplying. Functions. What we want is a function that takes a function as a parameter.Well, we said that with first-class functions, functions are values and can be passed as parameters. Let’s try it:Now we can use our function that takes functions as a parameter:This isbetter. When functions can take functions as parameters, we can build abstractions likeand save ourselves a lot of code. Note that this would be a lot harder to read if we had to surround all of our functions with Object boilerplate in Java. That’s one of the key reasons why ‘syntactic sugar’—making it brief—is a big win.And you know what? Functions are values, not just variables that happen to hold functions. These work just as well:There’s just one problem (actually two, but I’m saving one for later): everywhere you use our newfunction, you need to remember thatneeds a default value of zero, butneeds a default value of one. That’s bad. Sooner or later you will get this wrong.What we need is a way to callwithout having to always remember the correct initial value. Should we extend our understanding of a function to include a default initial value for folding? If we’re thinking in Java, maybe ourinterface needs a? I think not. Why should a function know anything about how it’s used? And besides, as we build other abstractions out of functions we’ll need more stuff.If we aren’t careful, we’ll end up implementing thepattern on functions, and all of our brevity will go out the window. No, what we want is this: in one place we define that folding addition starts with a default value of zero and in another place we say we want to fold, say,with addition. Then when we want to fold something else with addition, like, we shouldn’t have to say anything about zero again.What we need is a function that folds addition. Didn’t we say that functions are values that can be returned from functions? How about a function that makes a folding function? We should pass it our initial value and our binary function, and it should return a function that performs the fold without needing an initial value as a parameter:Now we can do the following:No more remembering that addition starts with a default of zero.Functional programmers (as opposed to the rest of us dysfunctional programmers) will recognize this as currying ourfunction. Currying is when a function takes more than one parameter and you combine one of the parameters and the function to produce a function that takes fewer parameters.Here’s a currying function in Ruby:(This is an improvement on an earlier version, thanks to Justin's comment .)So you can use our new function to create an increment function out of our adder and a treble function out of our multiplier:If you are ever asked, “what good is currying?,” I hope I’ve given you an example you can use to explain why currying matters, and why people do it all the time (possibly without explicitly naming it). Although it doesn’t look like much when looking at trivial examples like functions that multiply by three, it’s much more useful when creating folders and mappers where you want some of the parameters to remain constant.Our examples combined functions and non-functions to create new functions. Here’s an example from a recent post, Don’t Overthink FizzBuzz , where I give a method for composing two functions. The idea is that if you have multiple functions that each take one argument, you can combine them using. I also have a method that generates functions,The simple explanation of how it works is thatgenerates functions that replace every so many elements of a list with a printable string.composes any two or more methods together. So if you want to print out 100 numbers, but replace every third number with “Fizz,” every fifth with “Buzz,” and all those that are thirdfifth with “FizzBuzz,” you generate a function for each replacement, compose them together with compose, and then map the numbers from one to one hundred to the resulting überfunction.When you look at this today, it seems weird and unreadable by Java standards. I wonder if adding first-class functions with simple syntax to Java will lead the Java community to a place where code like this will not appear out of place?So we started by saying that people are getting hung up on what makes a closure a closure, and there has been less emphasis on the benefits of using functions as first-class values. Did you notice that ourfunction actually includes a non-trivial closure?If you look at thefunction, it makes use of, a variable from its enclosing lexical scope. This is not possible with the current version of Java: if you translate this to Java, when you makeand anonymous inner class, you will have to copyinto a final member to use it. It simply won’t compile if you try an idiom-for-idiom translation, even adding explicit types.And then if you look at the anonymous function it returns,, that anonymous function uses,another variable from the enclosing lexical scope. Once again you will have to fool around with final variables to make this work, or perhaps declare full-fledged object with constructors.(If you try writing this simple example out in Java, you quickly find yourself inventing a lot of classes or interfaces. And they have some complicated types, like a function taking an integer and a function taking two integers, returning a function taking a list of integers and returning an integer.After twenty minutes of that, you understand why the ML and Haskell communities use type inference : If the types are that complicated, it’s incredibly helpful to have the compiler check them for you. Yet if the types are that verbose, it’s incredibly painful to write them out by hand. Even if your IDE were to write them for you, they take up half the code, obscuring the meaning.You also get why the Ruby on Rails community doesn’t care about type checking: types for CRUD applications are way less complicated than types for first-class functional programs.)Part of the interest in closures is in simplifying the syntax around functions, and part of the interest is in the way that access to enclosing scope would simplify a lot of code. There’s a whole debate around the value of simplification in a world where all serious languages are Turing Equivalent For me, simpler is just nicer until something reaches a certain tipping point: when it becomes so simple that the accidental complexity of using it goes away, I will start using it without thinking about it. Tail optimization is like that: as long as recursion is slower than iteration and sometimes breaks, I have to think about it too much. But when I’m not burdened with “except…” and “when performance is not a factor…” it becomes natural.And then something interesting happens. It changes the way I look at problems, and one day I see a whole new way to do something that I never saw before. Functions as first class values are definitely one of those things that change everything.If this has whet your appetite for more, Structure and Interpretation of Computer Programs isbook on higher-order functions and how they can be used as building blocks to create more elaborate abstractions such as object-oriented programming. The Seasoned Schemer devotes an entire book to the uses of functions. Although the examples are in Scheme, the language is dead simple to learn and the techniques in the book can be applied to Ruby and Java (or at least to a future version of Java where you do not need functors).The second edition of Programming Ruby is an indispensable guide. Even if you will not be using Ruby immediately, pick it up and discover why so many people are lauding the language's simple, clean design and powerful Lisp-like underpinnings.As the author says, “ Higher-Order Perl: Transforming Programs with Programs is about functional programming techniques in Perl. It’s about how to write functions that can modify and manufacture other functions.“Why would you want to do that? Because that way your code is more flexible and more reusable. Instead of writing ten similar functions, you write a general pattern or framework that can generate the functions you want; then you generate just the functions you need according to the pattern. The program doesn’t need to know in advance which functions are necessary; it can generate them as needed. Instead of writing the complete program yourself, you get the computer to write it for you.”It’s worth reading even if you have no intention of using Perl: the ideas span languages, just as SICP is worth reading even if you don’t use Scheme at work. And be sure to read Higher-Order JavaScript and Higher-Order Ruby . They translate HOJ’s ideas to other languages. Some useful closures, in Ruby : “The Dylan programming language included four very useful functions for working with closures:and. The names are a bit obscure, but they can each be written in a few lines of Ruby.” From Functional to Object-Oriented Programming : “OO allows a traceable connection between the conceptual design level and the implementation level. Concepts have names, so you can talk about them, between programmers and architects.” HOF or OOP? Yes! : “First-class functions are a natural fit with OO, as evidenced by their presence in OO languages that aren’t glorified PDP-11 assemblers with some OO stuff bolted on the side.” But Y would I want to do a thing like this? : “To truly learn a new tool, you must not just learn the new tool, you must apply it to new kinds of problems. It’s no good learning to replace simple iteration with first-class functions: all you’ve learned is syntax. To really learn first-class functions, you must seek out problems that aren’t easily solved with iteration.”

Labels: java, lispy, popular, ruby