Showing posts with label functional. Show all posts
Showing posts with label functional. Show all posts

Monday, October 26, 2015

Approximating tuples in Java

What is a tuple? It's an ordered collection of individually typed elements. Wikipedia has a complicated explanation that comes down to the same thing in the context of ordinary programming. The Python implementation of tuples is a good example.

There are many related concepts, such as:

Arrays and lists
Ordered but all elements are the same type
Ordered dictionaries (maps)
Ordered but all values are of the same type, and they are named
Aggregates (structs, unions)
Individually typed but named and unordered

The closest matches to tuples in current Java are "structs" (more below) and arrays or lists, each with drawbacks. For most use of tuples, arrays and lists are non-starters: elements are all of the same nominal type. There is a lot of thought around how to do this best in Java.

What do I mean by saying Java has "structs" ala "C"? The vast bulk of Java code hides fields away with private, but exposes them with getter methods (and setters when non-final). This is the "Java Bean" anti-pattern. An alternative is to simply expose fields directly:

public final class CartesianPoint {
    public final int x;
    public final int y;

    public CartesianPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

This is almost a tuple. However:

  • CartesianPoint extends java.lang.Object but should not be an object in the OOP sense
  • Elements are accessed by name, e.g., point.x, rather than position
  • Elements are unordered—you cannot write a general function to process the first and second elements of the tuple without knowing 1) the struct type and 2) the names of the fields

But for many use cases this can be close enough, for example as a return type to simulate multiple value return. Hopefully Java 10 brings value types which resolves the java.lang.Object issue. This may even bring true tuples!

This example can be improved with Lombok:

@EqualsAndHashCode
@RequiredArgsConstructor(staticName = "valueOf")
@ToString(includeFieldNames = false)
public final class CartesianPoint {
    public final int x;
    public final int y;
}

Calling code would look like:

public CartesianPoint locate() {
    int x = computeX();
    int y = computeY();

    return CartesianPoint.valueOf(x, y);
}

Notice the visual similarity of the local variables x and y to the corresponding fields in CartesianPoint. Users of CartesianPoint would see:

public static void main(final String... args) {
    Boat boat = Boat.rowBoat();
    CartesianPoint point = boat.locate();

    out.printf("%s -> x is %d, y is %d%n", point, point.x, point.y);
}

$ ./float-boat 1 2
CartesianPoint(1, 2) -> x is 1, y is 2

If you want to go hog wild, the ordered and unnamed qualities of tuples can be simulated though not without significant noise:

Function<CartesianPoint, Integer> first = p -> p.x;
Function<CartesianPoint, Integer> second = p -> p.y;

out.printf("first is %d, second is %d%n",
        first.apply(point),
        second.apply(point));

Update

Streaming functionally:

Function<CartesianPoint, Integer> first = p -> p.x;
Function<CartesianPoint, Integer> second = p -> p.y;
Stream.of(first, second).
    map(f -> f.apply(point)).
    forEach(out::println);

Sunday, October 25, 2015

What's wrong with Java 8 series by Pierre-Yves Saumont

Pierre-Yves Saumont wrote a series of articles for DZone. I feel remiss for having missed them. For example, What's Wrong in Java 8, Part IV: Monads explores java.util.Optional. Do not be misled by the post titles—yes, he criticizes Java 8 for what it could have been—, but he covers functional thinking in Java with depth, skill and panache.

The full list of "What's Wrong with Java 8" articles:

  1. Currying vs Closures
  2. Functions & Primitives
  3. Streams and Parallel Streams
  4. Monads
  5. Tuples
  6. Strictness
  7. Streams again

And all his DZone articles.

Wednesday, October 21, 2015

Tracking Java 8 stream count

I had a coding problem to fail when a Java 8 stream was empty. One way is illustrated below in example1. Another approach was interesting, shown in example2

public final class Streamy {
    private static <T, E extends RuntimeException> void example1(
            final Stream<T> items,
            final Consumer<? super T> process,
            final Supplier<E> thrown)
            throws E {
        if (0 == items.
                peek(process).
                count())
            throw thrown.get();
    }

    private static <T, E extends RuntimeException> void example2(
            final Stream<T> items,
            final Consumer<? super T> process,
            final Supplier<E> thrown)
            throws E {
        final AtomicBoolean foundSome = new AtomicBoolean();
        try (final Stream<T> stream = items) {
            stream.
                    onClose(() -> {
                        if (!foundSome.get())
                            throw thrown.get();
                    }).
                    peek(__ -> foundSome.set(true)).
                    forEach(process);
        }
    }

    public static void main(final String... args) {
        example1(Stream.of(), out::println, RuntimeException::new);
        example2(Stream.of(), out::println, RuntimeException::new);
    }
}

Comparing them I find:

  • Using count() is shorter and more clear
  • Using onClose() is more expressive

I found it odd to use peek() in example1 to execute the real purpose of the code, and was happy to discover onClose() though disappointed to need try-with-resources for it to run.

It was unfortunate that the more expressive approach (peek() for side effect, forEach() for processing, onClose for post-processing check) was also harder to understand.

Tuesday, February 05, 2013

Java 8 lambdas and all that

Lovely post from Anton Arhipov at JRebel, Java 8: The First Taste of Lambdas. Kudos for javap decompilation for an "under the hood" explanation. His conclusion:

We can definitely say that lambdas and the accompanied features (defender methods, collections library improvements) will have a great impact on Java very soon. The syntax is quite nice and once developers realize that these features provide value to their productivity, we will see a lot of code that leverages these features.

It was quite interesting for me to see what lambdas are compiled to and I was very happy when I saw the total utilization of the invokedynamic instruction in action without any anonymous inner classes involved at all.

Sunday, November 25, 2012

Friday, February 17, 2012

Concatenative Programming

Jon Purdy on concatenative programming, which I had never heard of before. Basically it is purer functional programming for those of you who think Haskell is too corporate. (Actually, I enjoyed the read.)

P.S. — A remark from a clever fellow, no slouch he: That made my head hurt and reminded me of, when I was a freshman, trying to do a few chapters of Abelson & Sussman on my HP 28S calculator, which had RPN and (I realized) first-class functions.. I miss RPN calculators.

Thursday, December 15, 2011

Monad in Java

The shortest, clearest description of monads in Java I have read:

public class OptionalMonad {
    public static <T> Optional<T> unit(T value) {
        return Optional.of(value);
    }

    public static <T, U> Optional<U> bind(
            Optional<T> value,
            Function<T, Optional<U>> function) {
        if (value.isPresent()) return function.apply(value.get());
        else return Optional.absent();
    }
}

Thanks to François Sarradin in a very nice post.

Tuesday, October 18, 2011

Friday, September 11, 2009