Can someone explain what a functor is and provide a simple example?
In the functional programming paradigm, functions are first class objects in the language. That means that you can create an "instance" of a function, as have a variable reference that function instance, just like a reference to a String, Map or any other object.
A Functor is basically a Lambda, but one that is wrapped in an object. While functions cannot be passed into other functions as parameters, objects can. So essentially, Functors and Lambdas are a ways to pass around functions.
A function assigns to every element of a set X an element of a set Y. A functor assigns to every object of a category C an object of a category D and also assigns to every morphism in C a morphism in D in a way compatible with sources, targets, and composition.
In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type. Simple examples of this are Option and collection types.
A function object is just that. Something which is both an object and a function.
Aside: calling a function object a "functor" is a serious abuse of the term: a different kind of "functors" are a central concept in mathematics, and one that has a direct role in computer science (see "Haskell Functors"). The term is also used in a slightly different way in ML, so unless you are implementing one of these concepts in Java (which you can!) please stop using this terminology. It makes simple things complicated.
Back to the answer: Java does not have "first class functions" that is to say, you can not pass a function as an argument to a function. This true at multiple levels, syntactically, in the byte code representation, and in that the type system lacks the "function constructor"
In other words, you can't write something like this:
public static void tentimes(Function f){ for(int i = 0; i < 10; i++) f(); } ... public static void main{ ... tentimes(System.out.println("hello")); ... }
This is really annoying, since we want to be able to do things like have Graphical User Interface libraries where you can associate a "callback" function with clicking on a button.
So what do we do?
Well, the general solution (discussed by the other posters) is to define an interface with a single method that we can call. For example, Java uses an interface called Runnable
for these kinds of things all the time, it looks like:
public interface Runnable{ public void run(); }
now, we can rewrite my example from above:
public static void tentimes(Runnable r){ for(int i = 0; i < 10; i++) r.run(); } ... public class PrintHello implements Runnable{ public void run{ System.out.println("hello") } } --- public static void main{ ... tentimes(new PrintHello()); ... }
Obviously, this example is contrived. We could make this code a little bit nicer using anonymous inner classes, but this gets the general idea.
Here is where this breaks down: Runnable
is only usable for functions that don't take any arguments, and don't return anything useful, so you end up defining a new interface for each job. For example, the interface Comparator
in Mohammad Faisal's answer. Providing a more general approach, and one that takes syntax, is a major goal for Java 8 (The next version of Java), and was heavily pushed to be included in Java 7. This is called a "lambda" after the function abstraction mechanism in the Lambda Calculus. Lambda Calculus is both (perhaps) the oldest programming language, and the theoretical basis of much of Computer Science. When Alonzo Church (one of the main founders of computer science) invented it, he used the Greek letter lambda for functions, hence the name.
Other languages, including the functional language (Lisp, ML, Haskell, Erlang, etc), most of the major dynamic languages (Python, Ruby, JavaScript, etc) and the other application languages (C#, Scala, Go, D, etc) support some form of "Lambda Literal." Even C++ has them now (since C++11), although in that case they are somewhat more complicated because C++ lacks automatic memory management, and won't save your stack frame for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With