Table of Contents
Higher-order functions are functions that accept other functions
as parameters, or return functions as a result. In FunctionalJ, higher-order
functions are defined as static methods in the
Functions class.
Mapping consists of calling a 1-parameter function on each parameter of a list of parameters and returning a list of results:
map(f, [a1,a2,..,an]) = [f(a1), f(a2), .., f(an)]
For example:
DynReflect reflect = new JdkDynReflect(); Function1<String,String> upper = reflect.instanceFunction(String.class, "toUpperCase").f1(); List<String> strings = Arrays.asList("abcd", "EfGh", "IJ", "pL"); List<String> uppers = Functions.map(upper, strings); assertEquals(uppers, Arrays.asList("ABCD", "EFGH", "IJ", "PL"));
Filtering uses a 1-parameter function that returns a boolean
result to obtain, from a list of parameters, those for which the function returns
true::
filter(f, [a1,a2,..,an]) = ∪ an : f(an) == true
For example:
Function1<Boolean,Integer> negative = new Function1Impl<Boolean,Integer>() { public Boolean call(Integer p_value) { return p_value < 0; } }; List<Integer> values = Arrays.asList(1, 5, -4, -2, 0, 7); List<Integer> negatives = Functions.filter(negative, values); assertEquals(negatives, Arrays.asList(-4, -2));
You can also filter to obtain the values for which the function returns
false instead, using the
filterNot method:
filterNot(f, [a1,a2,..,an]) = ∪ an : f(an) == false
Function1<Boolean,Integer> negative = new Function1Impl<Boolean,Integer>() { public Boolean call(Integer p_value) { return p_value < 0; } }; List<Integer> values = Arrays.asList(1, 5, -4, -2, 0, 7); List<Integer> positives = Functions.filterNot(negative, values); assertEquals(positives, Arrays.asList(1, 5, 0, 7));
To determine if at least one element of a list satisfies a
condition determined by a function, you can use the
Functions.any. To determine if
all elements of a list satisfy the condition, you can use
Functions.all:
any(f, [a1,a2,..,an]) = ∃ n : f(an) == true
all(f, [a1,a2,..,an]) = ∀ n : f(an) == true
For example:
Function1<Boolean,Integer> negative = new Function1Impl<Boolean,Integer>() { public Boolean call(Integer p_value) { return p_value < 0; } }; List<Integer> values = Arrays.asList(1, 5, -4, -2, 0, 7); boolean anyNegative = Functions.any(negative, values); boolean allNegative = Functions.all(negative, values); assertTrue(anyNegative); assertFalse(allNegative);
Folding takes a function of 2 parameters
f, a parameter p,
and a collection of elements, to successively apply the function, each time using the
result of the previous function call as a parameter to the next function call. When
all elements have been processed, the result of the last function call is returned.
Folding can be performed from the left or from the right. Folding from the left starts the process at the left of the collection, and places the result of the previous function call on the left side of the next function call:
foldl(f, p, [a1,a2,..,an]) = f(f(f(f(p,a1),a2),..),an)
Folding from the right starts the process at the right of the collection, and places the result of the previous function call on the right side of the next function call:
foldr(f, p, [a1,a2,..,an]) = f(p,f(a1,f(a2,f(..,an))))
Folding can also be performed without an initial parameter. In this case, the folding
starts with the first two parameters at the left or at the right according to the
type of fold. Respectively, the methods are named
foldl1 and foldr1.
For example, to determine the maximum value from a list of values, we could fold the
max function into the list to obtain the result:
List<Integer> values = Arrays.asList(1, 5, -4, 7, 0, 2); int result = Functions.foldl1(Operators.max, values); assertEquals(result, 7);
Scanning is the same as folding, except that a list of each
successive result is returned rather than only the final result. The
scanl, scanl1,
scanr, scanr1 are
the counterparts of their folding equivalents.
Using scanning instead of folding in the previous example gives:
List<Integer> values = Arrays.asList(1, 5, -4, 7, 0, 2); List<Integer> results = Functions.scanl1(Operators.max, values); assertEquals(results, Arrays.asList(1, 5, 5, 7, 7, 7));