patternjavaMinor
Creating a pipeline operator in Java
Viewed 0 times
creatingpipelineoperatorjava
Problem
I wrote the following as more of an experiment than anything else, but I thought it would be fun to share and maybe get some feedback!
Motivation: I started looking at some functional languages and noticed how useful the
There are many common functions omitted from the
Consider the following example where static and instance methods are called on a stream:
With a pipeline
The following are the methods I wrote which enable piping
```
/**
* Perform a pipe operation on a parameter and a function.
* This follows the form: R = T |> F
*
* @param t The parameter to be applied
* @param f The fun
Motivation: I started looking at some functional languages and noticed how useful the
|> pipeline operator is. I started wondering how it might be translated to the Java language.There are many common functions omitted from the
Stream library that could be useful in expressing logic in a more clear fashion. For example, Stream does not have an instance method to concat with another stream-- you have to use a static method. This means that you can't easily chain concat to another operation within a stream; you have to wrap it within a method call. More examples include reversing, delays, zipping, etc. For each of these operations you have to make a helper method, and just like with concat you have to break chaining to wrap the partial solution within a method. This starts getting messy quickly, preventing authors from writing readable one-line expressions. Consider the following example where static and instance methods are called on a stream:
List foo = Stream
.concat(
reverseStream(
list1.stream()
.map(Some::func)
.flatMap(other::stuff)),
list2.stream()
.map(Some::func)
.flatMap(other::stuff)))
.map(Some::otherFunc)
.collect(Collectors.toList()) ...With a pipeline
|> operator, you could hide some complexity:List foo = list1 |> stream()
|> map(Some::func)
|> flatMap(other::stuff))
|> reverseStream()
|> concat(list1 |> stream()
|> map(Some::func)
|> flatMap(other::stuff))
|> map(Some::otherFunc)
|> collect(Collectors.toList());The following are the methods I wrote which enable piping
t |> f:```
/**
* Perform a pipe operation on a parameter and a function.
* This follows the form: R = T |> F
*
* @param t The parameter to be applied
* @param f The fun
Solution
This starts getting messy quickly, preventing authors from writing readable one-line expressions.
Based on this statement, I don't get, how you want to use your code. You definitely don't want to start programming in a string (see "evil eval"), nor is it getting less messy with the nested
What about a more
Maybe you could even implement
Based on this statement, I don't get, how you want to use your code. You definitely don't want to start programming in a string (see "evil eval"), nor is it getting less messy with the nested
pipe() calls.What about a more
java-approach. Just wrap the stream and add your methods. With some formatting, your are getting pretty close to your layout.import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Pipe
{
public static void main(String... args)
{
final List ints = Arrays.asList(1, 2, 3, 4, 5);
Pipe.of(ints)//
.concat(//
Pipe.of(ints)//
.reverse()//
)//
.forEach(System.out::println);
}
private static Pipe of(final List objects)
{
return new Pipe<>(objects);
}
private final Stream stream;
public Pipe(final List objects)
{
this(objects.stream());
}
private Pipe(final Stream stream)
{
this.stream = stream;
}
public Pipe concat(Pipe other)
{
return new Pipe<>(Stream.concat(stream, other.stream));
}
public Pipe reverse()
{
final List list = stream.collect(Collectors.toList());
Collections.reverse(list);
return new Pipe<>(list);
}
private void forEach(Consumer action)
{
stream.forEach(action);
}
}Maybe you could even implement
Stream, but I didn't checked this in detail.Code Snippets
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Pipe<O>
{
public static void main(String... args)
{
final List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5);
Pipe.of(ints)//
.concat(//
Pipe.of(ints)//
.reverse()//
)//
.forEach(System.out::println);
}
private static <O> Pipe<O> of(final List<O> objects)
{
return new Pipe<>(objects);
}
private final Stream<O> stream;
public Pipe(final List<O> objects)
{
this(objects.stream());
}
private Pipe(final Stream<O> stream)
{
this.stream = stream;
}
public Pipe<O> concat(Pipe<O> other)
{
return new Pipe<>(Stream.concat(stream, other.stream));
}
public Pipe<O> reverse()
{
final List<O> list = stream.collect(Collectors.toList());
Collections.reverse(list);
return new Pipe<>(list);
}
private void forEach(Consumer<O> action)
{
stream.forEach(action);
}
}Context
StackExchange Code Review Q#149775, answer score: 5
Revisions (0)
No revisions yet.