Straightforward Structural Pattern Matching

John McClean
4 min readFeb 23, 2016

--

Aficionados of languages such as Scala and Haskell (and soon C#) can take advantage of language level pattern matching. This allows users to safely deconstruct an Object into it’s constituent parts and trigger different outcomes depending on the values of those parts.

In Scala we can directly match on values, as above (much like a switch statement), or we can deconstruct an Object.

In the example above a List is deconstructed into it’s head and tail components. Sharp Java readers will notice this is just like the visitor pattern common in OO languages. We could (for example) visit the head and tail of a List recursively to reduce it to a single String

Note, in practice we would be better off using an iterative reduce / fold / join method call on the List. But we can replicate this functionality & method in Java with the Visitor pattern. Let’s imagine a List eXtension class with a visit method that returns access to the head and tail. Then we can rewrite the Scala code like so

In fact this is one of the many features of the cyclops-react library, and we take this structural type pattern matching much further.

Pattern Matching for Java

Let’s introduce the cyclops-react Matchable class, which provides a when / then/ otherwise dsl for pattern matching. We can rewrite our first Scala example that converts from numerics to Strings as follows.

We could also extend this further, in a type-safe manner to handle an Optional (or cyclops-react Maybe).

Note the use of the Predicates class and lessThan in this example. With full type-safety we can match directly on a value or compose matching statements with Predicates.

Matching with Predicates

cyclops-react implements structural pattern matching via Predicates. This means you can apply structural pattern matching anywhere a JDK java.util.function.predicate is accepted. Within the library itself the Matchable class provides a when / then / otherwise syntax for building matching cases, and Matchables provides access to structurally deconstructable JDK classes.

The Predicates class

The Predicates class in cyclops-react contains a lot of useful, compositional Predicates that can be used anywhere Predicates are accepted (for example within Stream, or within cyclops-react pattern matching).

In the example above we compose predicates to select the elements in a Stream we wish to retain, in this case only the number 1 will be selected by the filter as it passes at least one of the 2 composed predicates (passing both in fact).

Matchables

Within a Stream the Matchables class provides static methods that can used to map JDK Objects to a form where structural pattern matching is possible.

The example above shows structural pattern matching on the properties of java.net.URL, within a JDK Stream. on$12_45 says that we only wish to match on the first, second, fourth and fifth part of the URL, where the URL is broken down a documented fashion into it’s protocol, domain, path, port and query.

Deconstructing an object

Predicates.decons method can be used to deconstruct POJOs so that their sub-components can be matched.

The example above shows how to use the decons Predicate when performing Structural Pattern Matching with cyclops-react, but we can also use the same Predicate when filtering within a Stream.

Matchable.from allows users to provide a mechanism to deconstruct any Java Object by providing a lambda expression (or java.util.function.Supplier instance) that access each of it’s interesting component fields.

Deconstructing when filtering

We can reuse the same technique to filter Customers by Address from within a Stream

If you like this you might like to check out cyclops-react :

--

--

John McClean

Architecture @ Verizon Media. Maintainer of Cyclops. Twitter @johnmcclean_ie