groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject [groovy] branch master updated: GROOVY-9169: Groovy could support andThen/compose aliases for rightShift/leftShift (closes #952)
Date Mon, 17 Jun 2019 07:07:00 GMT
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 5d46759  GROOVY-9169: Groovy could support andThen/compose aliases for rightShift/leftShift
(closes #952)
5d46759 is described below

commit 5d4675988fc58a06553343039cb8b4943f035908
Author: Paul King <paulk@asert.com.au>
AuthorDate: Tue Jun 11 21:06:05 2019 +1000

    GROOVY-9169: Groovy could support andThen/compose aliases for rightShift/leftShift (closes
#952)
---
 src/main/java/groovy/lang/Closure.java    | 60 +++++++++++++++++++++++++++
 src/test/groovy/ClosureComposeTest.groovy | 68 +++++++++++++++++++++++++++++++
 2 files changed, 128 insertions(+)

diff --git a/src/main/java/groovy/lang/Closure.java b/src/main/java/groovy/lang/Closure.java
index 6464a2d..f91c5f0 100644
--- a/src/main/java/groovy/lang/Closure.java
+++ b/src/main/java/groovy/lang/Closure.java
@@ -657,6 +657,66 @@ public abstract class Closure<V> extends GroovyObjectSupport implements
Cloneabl
     }
 
     /**
+     * Alias for {@link #rightShift(Closure)}
+     *
+     * @return the newly composed closure
+     */
+    public <W> Closure<W> andThen(final Closure<W> other) {
+        return rightShift(other);
+    }
+
+    /**
+     * Call {@link #andThen(Closure)} on {@code this}.
+     *
+     * @return the newly composed closure
+     */
+    public Closure<V> andThenSelf() {
+        return andThen(this);
+    }
+
+    /**
+     * Call {@link #andThen(Closure)} on {@code this} exactly {@code times} times.
+     *
+     * @param times the number of times to reverse compose the closure with itself
+     * @return the newly composed closure
+     */
+    public Closure<V> andThenSelf(int times) {
+        if (times == 0) return this;
+        if (times == 1) return andThen(this);
+        return andThen(andThenSelf(times - 1));
+    }
+
+    /**
+     * Alias for {@link #leftShift(Closure)}
+     *
+     * @return the newly composed closure
+     */
+    public Closure<V> compose(final Closure other) {
+        return leftShift(other);
+    }
+
+    /**
+     * Call {@link #compose(Closure)} on {@code this}.
+     *
+     * @return the newly composed closure
+     */
+    public Closure<V> composeSelf() {
+        return compose(this);
+    }
+
+    /**
+     * Call {@link #compose(Closure)} on {@code this} exactly {@code times} times.
+     *
+     * @param times the number of times to compose the closure with itself
+     * @return the newly composed closure
+     */
+    public Closure<V> composeSelf(int times) {
+        if (times == 0) return this;
+        if (times == 1) return compose(this);
+        return compose(composeSelf(times - 1));
+    }
+
+    /**
      * Alias for calling a Closure for non-closure arguments.
      * <p>
      * Typical usage:
diff --git a/src/test/groovy/ClosureComposeTest.groovy b/src/test/groovy/ClosureComposeTest.groovy
index 2f759a5..75eaab1 100644
--- a/src/test/groovy/ClosureComposeTest.groovy
+++ b/src/test/groovy/ClosureComposeTest.groovy
@@ -18,6 +18,10 @@
  */
 package groovy
 
+import groovy.transform.CompileStatic
+
+import java.util.function.Function
+
 /**
  * Tests for Closure composition
  */
@@ -100,6 +104,70 @@ class ClosureComposeTest extends GroovyTestCase {
         """
     }
 
+    @CompileStatic
+    void testAndThenCS() {
+        Function<String, String> lower = String::toLowerCase
+        Function<String, String> upper = String::toUpperCase
+        Function<String, String> lu = lower.andThen(upper)
+        Function<? super String, String> ul = upper.andThen(lower)
+        assert lower('Hi') == ul('Hi')
+        assert upper('Hi') == lu('Hi')
+    }
+
+    void testAndThen() {
+        def lower = String::toLowerCase
+        def upper = String::toUpperCase
+        def lu1 = lower.rightShift(upper)
+        def ul1 = upper.rightShift(lower)
+        assert lower('Hi') == ul1('Hi')
+        assert upper('Hi') == lu1('Hi')
+        def lu2 = lower.andThen(upper)
+        def ul2 = upper.andThen(lower)
+        assert lower('Hi') == ul2('Hi')
+        assert upper('Hi') == lu2('Hi')
+    }
+
+    void testAndThenSelf() {
+        def inc = String::next
+        def inc2 = inc.andThenSelf()
+        def inc4 = inc.andThenSelf(3)
+        assert inc('abc') == 'abd'
+        assert inc2('abc') == 'abe'
+        assert inc4('abc') == 'abg'
+    }
+
+    @CompileStatic
+    void testComposeCS() {
+        Function<String, String> lower = String::toLowerCase
+        Function<String, String> upper = String::toUpperCase
+        Function<String, String> ul = lower.compose(upper)
+        Function<String, ? extends String> lu = upper.compose(lower)
+        assert lower('Hi') == ul('Hi')
+        assert upper('Hi') == lu('Hi')
+    }
+
+    void testCompose() {
+        def lower = String::toLowerCase
+        def upper = String::toUpperCase
+        def ul1 = lower.leftShift(upper)
+        def lu1 = upper.leftShift(lower)
+        assert lower('Hi') == ul1('Hi')
+        assert upper('Hi') == lu1('Hi')
+        def ul2 = lower.compose(upper)
+        def lu2 = upper.compose(lower)
+        assert lower('Hi') == ul2('Hi')
+        assert upper('Hi') == lu2('Hi')
+    }
+
+    void testComposeSelf() {
+        def inc = String::next
+        def inc2 = inc.composeSelf()
+        def inc4 = inc.composeSelf(3)
+        assert inc('abc') == 'abd'
+        assert inc2('abc') == 'abe'
+        assert inc4('abc') == 'abg'
+    }
+
     class ComposeTestHelper {
         def closure1 = { 40 }
         def closure2 = { it * 40 }


Mime
View raw message