0

Somehow I should be able to specify a chain like this while value is piped through each function.

a::create -> a::processing -> a::updating -> a:uploading

In context of following articles I want to chain the methods with one method passing the result to the next while modifying it.

https://dzone.com/articles/higher-order-functions

https://dzone.com/articles/functional-programming-java-8

my demo will try to show what I want as the end result. It's going to be a single parameter/argument piped to each method (like monads) and should be easier to specify an arbitrary number of methods in a chain.

I've been doing this in other languages so trying to get my head around in how to do in java.

All methods will receive same type of argument and only one.

Class Value

public class Value {
    public String progress = "";
}

Class Article

public class Article {

    public void create(Value value) {
        value.progress += "creating ";
    }

    public void processing(Value value) {
        value.progress += "processing ";
    }

    public void updating(Value value) {
        value.progress += "updating ";
    }

    public void uploading(Value value) {
        value.progress += "uploading ";
    }

}

Main Class

public class Main {

    public static void main(String[] args) {
        Value v = new Value();
        Article a = new Article();

        a.create(v);
        a.processing(v);
        a.updating(v);
        a.uploading(v);
    }
}

Suggested Link

Community
  • 1
  • 1
user2727195
  • 7,122
  • 17
  • 70
  • 118
  • @JDC please remove the tag, the answer is theoretical only and doesn't help me, I need a working example – user2727195 Mar 14 '17 at 08:16
  • 2
    You should probably take this to software engineering (and maybe with less condescension/grumpiness, if you hope to have people talk to you about it). – pvg Mar 14 '17 at 08:19
  • no, didn't mean that, will post there – user2727195 Mar 14 '17 at 08:21
  • By the way, minor typo value.progress = "updating "; should be value.progress += "updating "; – Neil Mar 14 '17 at 08:24
  • thanks @nfnneil, question updated. – user2727195 Mar 14 '17 at 08:25
  • If that's the entirety of the `Article` class, can't you just replace each method with a function that you can then compose? – Steve Chaloner Mar 14 '17 at 08:26
  • @SteveChaloner it's a very narrow down example, the actual implementation has each function with remote services and database calls. – user2727195 Mar 14 '17 at 08:27
  • @pvg when referring other sites, it is often helpful to point that [cross-posting is frowned upon](http://meta.stackexchange.com/tags/cross-posting/info) – gnat Mar 14 '17 at 08:29
  • I'm not sure which portal is best for this question, I can delete the other one – user2727195 Mar 14 '17 at 08:30
  • If you want better FP support in Java 8, I really recommend [Javaslang](http://www.javaslang.io/). It's way more rational than the core Java equivalents. – Steve Chaloner Mar 14 '17 at 08:40
  • 2
    I'm a bit confused by your question: there is no monad in your code, so what is it that you actually want to compose? – Jörg W Mittag Mar 14 '17 at 09:00
  • @JörgWMittag, yes there's no, I wrote non monad based and trying to convert, however, my attempted answer is close to what I want to achieve, please have a look – user2727195 Mar 14 '17 at 09:04
  • Try this using your original article class as mentioned in the question with modified methods to be static: `((Consumer) Article::create).andThen(Article::processing).accept(new Value());` this will modify your value as expected. – JDC Mar 14 '17 at 10:14
  • @JDC can you please add complete solution as an answer, I'm not so fluent with java – user2727195 Mar 14 '17 at 15:22

3 Answers3

5

Given that immutable state is preferable in functional programming, I've tweaked Value - this has the added benefit of making the progress functions cleaner.

public class Value {
    public final String progress;

    public Value() {
        this("");
    }

    public Value(final String progress) {
        this.progress = progress;
    }
}

In place of methods, Article then has functions. These functions can be chained using andThen.

import java.util.function.Function;

public class Article {

    private final Function<Value, Value> create = v -> new Value(v.progress + "creating ");
    private final Function<Value, Value> processing = v -> new Value(v.progress + "processing ");
    private final Function<Value, Value> updating = v -> new Value(v.progress + "updating ");
    private final Function<Value, Value> uploading = v -> new Value(v.progress + "uploading ");

    public static void main(String[] args) {
        final Article a = new Article();
        final Value v = a.create.andThen(a.processing).andThen(a.updating).andThen(a.uploading).apply(new Value());

        System.out.println(v.progress);
    }
}

The result of System.out.println is then creating processing updating uploading.

Update

Based on your preference to have the functions created in methods, you just need to change your Article implementation to have something like this. Note that I'm using your original (mutable) implementation of Value.

public class Article {

    public Function<Value, Value> create() {
        return v -> {
            v.progress += "creating ";
            return v;
        };
    }

    public Function<Value, Value> processing() {
        return v -> {
            v.progress += "processing ";
            return v;
        };
    }

    public Function<Value, Value> updating() {
        return v -> {
            v.progress += "updating ";
            return v;
        };
    }

    public Function<Value, Value> uploading() {
        return v -> {
            v.progress += "uploading ";
            return v;
        };
    }

    public static void main(String[] args) {
        final Article a = new Article();
        final Value v = a.create()
                         .andThen(a.processing())
                         .andThen(a.updating())
                         .andThen(a.uploading())
                         .apply(new Value());

        System.out.println(v.progress);
    }
}

Update 2

Static method references have been requested, so here you go. I will add a proviso that if anyone presented me with this code, I would want a damn good reason for the design choice.

public class Article {

    public static Value create(Value v) {
        v.progress += "creating ";
        return v;
    }

    public static Value processing(Value v) {
        v.progress += "processing ";
        return v;
    }

    public static Value updating(Value v) {
        v.progress += "updating ";
        return v;
    }

    public static Value uploading(Value v) {
        v.progress += "uploading ";
        return v;
    }


    public static void main(String[] args) {
        Optional<Value> maybeValue = Stream.of(new Value())
                                           .map(Article::create)
                                           .map(Article::processing)
                                           .map(Article::updating)
                                           .map(Article::uploading)
                                           .findFirst();

        maybeValue.ifPresent(v -> System.out.println(v.progress));
    }
}
Steve Chaloner
  • 8,162
  • 1
  • 22
  • 38
  • it's good. I'm editing few things and I applied your `Value` proposition but compiler is complaining because of final string, also when you say immutable, my idea is object getting decorated with updated values through the chain – user2727195 Mar 14 '17 at 08:42
  • can we have the article class return `Value` or `Function – user2727195 Mar 14 '17 at 08:47
  • please have a look at my answer – user2727195 Mar 14 '17 at 09:06
  • bravo, this is what I wanted but I learned about immutability from you, you can update to be immutable so it helps well others. millions of thanks. – user2727195 Mar 14 '17 at 09:24
  • also a question, if I mark Article methods as static, then `a.processing()` will become `a::processing()`, right so I don't have to create an object for `Article`? – user2727195 Mar 14 '17 at 09:27
  • is there a handler for fault just like `.andThen` or `.apply`, at the end of the chain or should I put `try/catch` wrapping the chain? – user2727195 Mar 14 '17 at 09:34
  • @user2727195 If your functions aren't single liners, you can just use method references, so for `private Value complicatedAction(Value in) {...}` you can have `public Function COMPLICATED_ACTION = this::complicatedAction;` It's probably the most readable solution. – biziclop Mar 14 '17 at 15:57
  • @SteveChaloner please read JDC's last commend under the question where he's suggesting static functions and using `::` operator, can you please one more time, add another Edit to the question – user2727195 Mar 14 '17 at 19:36
  • @user2727195 using method references means you will have methods and method references that refer to them. Also, just modifying the methods to be static is meaningless if they don't return anything. I don't see that comment as being useful. But, I've edited to include the use of static method references. – Steve Chaloner Mar 15 '17 at 08:05
  • @SteveChaloner - as Babbage said "I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question." Your first answer was fine; each successive edit made it worse... – jon hanson Mar 27 '17 at 22:32
  • @jon-hanson I absolutely agree. Successive edits were made at the request of the OP, but are approaches I would never use. – Steve Chaloner Mar 28 '17 at 07:39
1

Here's one way of chaining with Java8 Streams.

public static class Article {

    public Stream<Value> create(Value value) {
        value.progress += "creating ";
        return Stream.of(value);
    }

    public Stream<Value> processing(Value value) {
        value.progress += "processing ";
        return Stream.of(value);
    }

    public Stream<Value> updating(Value value) {
        value.progress += "updating ";
        return Stream.of(value);
    }

    public Stream<Value> uploading(Value value) {
        value.progress += "uploading ";
        return Stream.of(value);
    }

    public Stream<Value> error(Value value) {
        return Stream.empty();
    }

}

public static void main(String[] args) {

    Article a = new Article();

    Stream.of(new Value())
            .flatMap(a::create)
            .flatMap(a::processing)
            .flatMap(a::updating)
            .flatMap(a::uploading)
            .forEach(v -> System.out.println(v.progress));

    Stream.of(new Value())
            .flatMap(a::create)
            .flatMap(a::processing)
            .flatMap(a::updating)
            .flatMap(a::error)
            .forEach(v -> System.out.println(v.progress));

}

Output:

creating processing updating uploading

Doing this without modifying Article methods to return Stream

public static class Article {

    public Value create(Value value) {
        value.progress += "creating ";
        return value;
    }

    public Value processing(Value value) {
        value.progress += "processing ";
        return value;
    }

    public Value updating(Value value) {
        value.progress += "updating ";
        return value;
    }

    public Value uploading(Value value) {
        value.progress += "uploading ";
        return value;
    }

}

@FunctionalInterface
public interface ThrowingFunction<T, R> {
    R apply(T v) throws Exception;
}

public static Function<Value, Stream<Value>> wrap(ThrowingFunction<Value, Value> call) {
    return (Value v) -> {
        try {
            return Stream.of(call.apply(v));
        } catch (Exception e) {
            return Stream.empty();
        }
    };
}

public static void main(String[] args) {

    Article a = new Article();

    Stream.of(new Value())
            .flatMap(wrap(a::create))
            .flatMap(wrap(a::processing))
            .flatMap(wrap(a::updating))
            .flatMap(wrap(a::uploading))
            .forEach(v -> System.out.println(v.progress));

}
Mark Mucha
  • 1,560
  • 2
  • 12
  • 18
  • Can you please edit and add another section on how can I use it without returning Stream, like Steve example, using `andThen` but then keeping everything intact the way it is. my methods have substantial bodies and I can't have them defined inline so your article definition is good – user2727195 Mar 14 '17 at 08:49
  • please have a look at my answer – user2727195 Mar 14 '17 at 09:06
0

It's not answer and it doesn't work but something I drafted based on the given answers to get close to what I want. please post your edits/answer based on this.

Value

public class Value {
    public String progress = "";
}

Article - you may modify the signature of methods to suit the needs.

public class Article {

    public Value create(Value value) {
        value.progress += "creating ";
        return value;
    }

    public Value processing(Value value) {
        value.progress += "processing ";
        return value;
    }

    public Value updating(Value value) {
        value.progress = "updating ";
        return value;
    }

    public Value uploading(Value value) {
        value.progress += "uploading ";
        return value;
    }
}

Main (I should be able to do something like this)

public class Main {

    public static void main(String[] args) {
        Article a = new Article();

        final Value v = a.create
                .andThen(a.processing) // or a::processing
                .andThen(a.updating)   // or a::updating
                .andThen(a.uploading)
                .apply(new Value());

        System.out.println(v.progress);
    }
}
user2727195
  • 7,122
  • 17
  • 70
  • 118