├── .gitignore ├── .github └── dependabot.yml ├── pom.xml ├── src ├── test │ └── java │ │ └── co │ │ └── nstant │ │ └── in │ │ └── pipe │ │ └── PipeTest.java └── main │ └── java │ └── co │ └── nstant │ └── in │ └── pipe │ └── Pipe.java ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings/ 4 | target/ 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | co.nstant.in 5 | java-pipe 6 | 1.0.0 7 | 8 | 9 | junit 10 | junit 11 | 4.13.2 12 | test 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/java/co/nstant/in/pipe/PipeTest.java: -------------------------------------------------------------------------------- 1 | package co.nstant.in.pipe; 2 | 3 | import static co.nstant.in.pipe.Pipe.apply; 4 | import static org.junit.Assert.assertEquals; 5 | 6 | import org.junit.Test; 7 | 8 | public class PipeTest { 9 | 10 | @Test 11 | public void testPipe() { 12 | assertEquals("11", apply("ab") 13 | .pipe((a) -> a.toUpperCase()) 14 | .pipe((a, b) -> a.replace('A', b), '1') 15 | .pipe((a, b, c) -> a.replace(b, c), 'B', '2') 16 | .pipe((a) -> Integer.valueOf(a)) 17 | .pipe((a, b, c, d) -> a + b * c - d, 1, 2, 3) 18 | .pipe((a) -> a.toString()) 19 | .result()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Constantin Rack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # java-pipe 2 | 3 | Implementation of the [Elixir pipe operator](https://elixirschool.com/en/lessons/basics/pipe-operator/) behavior in Java. 4 | 5 | Functions with up to 3 (TriFunction) respectively 4 (QuadriFunction) arguments are supported. 6 | 7 | ## Description 8 | 9 | In [Elixir](https://elixir-lang.org/), 10 | a value can be passed to a function using the pipe operator (`|>`), 11 | where the value is automatically used as first argument of the function. 12 | 13 | While Java 8 has introduced [function composition](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html) with `.andThen()`, it is not exactly what I was searching for when trying to mimic 14 | Elixir's pipe operator in Java. So I wrote this small class and hope someone finds it useful. 15 | 16 | ## Usage example 17 | 18 | ```java 19 | apply("ab") 20 | .pipe((a) -> a.toUpperCase()) // "AB" 21 | .pipe((a, b) -> a.replace('A', b), '1') // "1B" 22 | .pipe((a, b, c) -> a.replace(b, c), 'B', '2') // "12" 23 | .pipe((a) -> Integer.valueOf(a)) // 12 24 | .pipe((a, b, c, d) -> a + b * c - d, 1, 2, 3) // 11 25 | .pipe((a) -> a.toString()) // "11" 26 | .result() 27 | ``` 28 | -------------------------------------------------------------------------------- /src/main/java/co/nstant/in/pipe/Pipe.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of the Elixir pipe operator behavior in Java. 3 | * 4 | * Copyright (c) 2017 Constantin Rack 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | package co.nstant.in.pipe; 25 | 26 | import java.util.function.BiFunction; 27 | import java.util.function.Function; 28 | 29 | public class Pipe { 30 | 31 | @FunctionalInterface 32 | public interface TriFunction { 33 | 34 | R apply(A a, B b, C c); 35 | 36 | } 37 | 38 | @FunctionalInterface 39 | public interface QuadriFunction { 40 | 41 | R apply(A a, B b, C c, D d); 42 | 43 | } 44 | 45 | public final A a; 46 | 47 | private Pipe(A a) { 48 | this.a = a; 49 | } 50 | 51 | public static Pipe apply(A a) { 52 | return new Pipe(a); 53 | } 54 | 55 | public Pipe pipe(Function f) { 56 | return new Pipe(f.apply(a)); 57 | } 58 | 59 | public Pipe pipe(BiFunction f, B b) { 60 | return new Pipe(f.apply(a, b)); 61 | } 62 | 63 | public Pipe pipe(TriFunction f, B b, C c) { 64 | return new Pipe(f.apply(a, b, c)); 65 | } 66 | 67 | public Pipe pipe(QuadriFunction f, B b, C c, D d) { 68 | return new Pipe(f.apply(a, b, c, d)); 69 | } 70 | 71 | public A result() { 72 | return a; 73 | } 74 | 75 | } 76 | --------------------------------------------------------------------------------