runarorama / runarorama.github.com

9 stars 3 forks source link

Structural Pattern Matching in Java #14

Open runarorama opened 9 years ago

jbgi commented 9 years ago

Yes! So much Java code is a mess because of not implementing proper Sum types.

Readers of this post might be interested in Derive4j - https://github.com/derive4j/derive4j - a project that try to industrialize a variant of this technique (through annotation processing).

nbardiuk commented 8 years ago

@runarorama Thank you for the post. I've found it very useful for my java8 projects. I've used your approach and went little bit further by decomposing matched objects:

int depth(Tree t) {
    return t.match(empty -> 0,
                   leaf(n -> 1),
                   node((left, right) -> 1 + max(depth(left), depth(right))));
}

Where leaf and node are helper functions:

<T> Function<Leaf, T> leaf(Function<Integer, T> function) {
    return leaf -> function.apply(leaf.n);
}

<T> Function<Node, T> node(BiFunction<Tree, Tree, T> function) {
    return node -> function.apply(node.left, node.right);
}

But this approach has limitation - standard java8 library has only unary and binary functional objects. Currying can help but it less readable

int depth(Tree t) {
    return t.match(empty -> 0,
                   leaf(n -> 1),
                   node(left -> right -> 1 + max(depth(left), depth(right))));
}

<T> Function<Node, T> node(Function<Tree, Function<Tree, T>> function) {
    return node -> function.apply(node.left).apply(node.right);
}
smillies commented 8 years ago

I was just redirected here from the JOOQ blog. Thanks for the post. Perhaps you'd be interested in cyclops-react, a functional library that implements structural pattern matching for Java through java.util.Predicate, so you can pattern-match in your code wherever a predicate is accepted. Resulting code is not quite as terse as yours, but you don't need to implement anything in your own datatypes. Cyclops is also here on GitHub (I'm not involved). And here's the article about the pattern-matching stuff. -- Sebastian

unautre commented 5 years ago

Hello, I just stumbled upon your article, and found it very interesting ; I'm myself trying to learn FP while being a OOP Java programmer, and right now it's not exactly easy. I wanted to leave a comment because, in this article, you're saying the visitor pattern is ugly, but the visitor interface is just an aggregate of the threes lambdas you're passing around in the "good" solution ; isn't a data object objectively better and easier to extends than passing 3 arguments everywhere ? Or is it just me that is seeing everything through my thick OOP lenses ?