Over a million developers have joined DZone.

Functional Programming: Predicate + Function = Rule

· Java Zone

Discover how powerful static code analysis and ergonomic design make development not only productive but also an enjoyable experience, brought to you in partnership with JetBrains

I want to share with you a little gadget that uses google-collections. Basically, a rule is a condition and an action.
So I will use Predicate as a condition and Function as an action. The composite function then consists of list of rules, for the first predicate that evaluates to true, it will invoke the corresponding function. If none of the predicates are matched - default function will be invoked.

For example, here is how I define a function "size" of an arbitrary object:

Function<Object, Integer> size = new Rules<Object,Integer>().
addRule(isNull(), constant(0)).
addRule(
or(
instanceOf(Collection.class),
instanceOf(Map.class)),
self().reflect("size").cast(Integer.class)).
addRule(
asPredicate(self().reflect("getClass").
reflect("isArray").cast(Boolean.class)),
self().reflect(Array.class, "getLength").cast(Integer.class)).
setDefault(constant(1));
If you read my earlier post, you already know about the FunctionChain, this is where I statically import self() from. The reflect() function transfers Object to Object by invoking a parameterless method with given name on the current object, or passes current object to a single-parameter method of another object (or class for static methods). The cast() method performs a cast to given class. The instanceOf() function is a shortcut to ClassPredicate which returns true if the class it holds is assignable from a given class. I also assume statically imported or and isNull Predicates and Functions.constant. (I could replace reflect function calls with a special size and length functions, but I think it's enough to illustrate the idea as it is.)

The same segment in "normal" coding would look something like that:
if (object == null) {
return 0;
} else if (object instanceof Collection) {
return ((Collection)object).size(); {
} else if (object instanceof Map) {
return ((Map)object).size(); {
} else if (object.getClass().isArray()) {
return Array.getLength(object);
} else {
return 1;
}

I don't pretend one is better than the other, but it's interesting enough, I think, and sometimes useful.

Here is the source code for Rules class:

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import java.util.Collection;
import java.util.LinkedList;

public class Rules<F,T> extends LinkedList<Rules.Rule<F,T>> implements Function<F,T> {
private Function<? super F, ? extends T> defaultFunction = null;

public Rules() {
super();
}

public Rules(Collection<? extends Rules.Rule<F,T>> c) {
super(c);
}

public Rules<F,T> addRule(Predicate<? super F> condition, Function<? super F, ? extends T> action) {
add(new Rule<F,T>(condition, action));
return this;
}

public Function<? super F, ? extends T> getDefault() {
return defaultFunction;
}

public Rules<F,T> setDefault(Function<? super F, ? extends T> defaultFunction) {
this.defaultFunction = defaultFunction;
return this;
}

public Rules<F,T> noDefault() {
setDefault(null);
return this;
}

public T apply(F from) {
for (Rule<F,T> rule: this) {
if (rule.getPredicate().apply(from)) return rule.getFunction().apply(from);
}
Function<? super F, ? extends T> def = getDefault();
return def != null ? def.apply(from) : null;
}

public static final class Rule<A,B> {
private final Predicate<? super A> predicate;
private final Function<? super A, ? extends B> function;

public Rule(Predicate<? super A> predicate, Function<? super A, ? extends B> function) {
this.predicate = predicate;
this.function = function;
}

public Predicate<? super A> getPredicate() {
return predicate;
}

public Function<? super A, ? extends B> getFunction() {
return function;
}
}

}

 

Learn more about Kotlin, a new programming language designed to solve problems that software developers face every day brought to you in partnership with JetBrains.

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}