You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/04/10 08:36:08 UTC

[groovy] branch master updated: GROOVY-9008: initial cut at doco

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 4ce4cce  GROOVY-9008: initial cut at doco
4ce4cce is described below

commit 4ce4cce8741354beb8129f4adedbbe99ce5f1110
Author: Paul King <pa...@asert.com.au>
AuthorDate: Wed Apr 10 18:35:57 2019 +1000

    GROOVY-9008: initial cut at doco
---
 src/spec/doc/core-differences-java.adoc            |  12 +--
 src/spec/doc/core-operators.adoc                   |  41 ++++++++-
 src/spec/test/OperatorsTest.groovy                 |  48 ++++++++--
 .../transform/stc/MethodReferenceTest.groovy       | 102 +++++++--------------
 4 files changed, 118 insertions(+), 85 deletions(-)

diff --git a/src/spec/doc/core-differences-java.adoc b/src/spec/doc/core-differences-java.adoc
index 9e66163..1170704 100644
--- a/src/spec/doc/core-differences-java.adoc
+++ b/src/spec/doc/core-differences-java.adoc
@@ -201,18 +201,18 @@ There is a danger that you will write new X() instead of new X(this) for
 example. Since this might also be the regular way we have not yet found
 a good way to prevent this problem.
 
-== Lambdas
+== Lambda expressions and the method reference operator
 
-Java 8 supports lambdas and method references:
+Java 8+ supports lambda expressions and the method reference operator (`::`):
 
-[source,groovy]
+[source,java]
 ----
-Runnable run = () -> System.out.println("Run");
+Runnable run = () -> System.out.println("Run");  // Java
 list.forEach(System.out::println);
 ----
 
-Java 8 lambdas can be more or less considered as anonymous inner classes. Groovy doesn't support that syntax, but has closures
-instead:
+Groovy 3 and above also support these within the Parrot parser.
+In earlier versions of Groovy you should use closures instead:
 
 [source,groovy]
 ----
diff --git a/src/spec/doc/core-operators.adoc b/src/spec/doc/core-operators.adoc
index 716d1eb..7fa2566 100644
--- a/src/spec/doc/core-operators.adoc
+++ b/src/spec/doc/core-operators.adoc
@@ -326,12 +326,12 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=direct_field_op,in
 [[method-pointer-operator]]
 === Method pointer operator
 
-The method pointer operator (`.&`) call be used to store a reference to a method in a variable, in order to call it
-later:
+The method pointer operator (`.&`) can be used to store a reference to a method in a variable,
+in order to call it later:
 
 [source,groovy]
 ----
-include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference,indent=0]
+include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_pointer,indent=0]
 ----
 <1> the `str` variable contains a `String`
 <2> we store a reference to the `toUpperCase` method on the `str` instance inside a variable named `fun`
@@ -344,7 +344,7 @@ convert an existing method for the needs of the strategy pattern:
 
 [source,groovy]
 ----
-include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference_strategy,indent=0]
+include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_pointer_strategy,indent=0]
 ----
 <1> the `transform` method takes each element of the list and calls the `action` closure on them, returning a new list
 <2> we define a function that takes a `Person` and returns a `String`
@@ -358,7 +358,7 @@ will be done at runtime:
 
 [source,groovy]
 ----
-include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference_dispatch,indent=0]
+include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_pointer_dispatch,indent=0]
 ----
 <1> define an overloaded `doSomething` method accepting a `String` as an argument
 <2> define an overloaded `doSomething` method accepting an `Integer` as an argument
@@ -366,6 +366,37 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_reference_d
 <4> using the method pointer with a `String` calls the `String` version of `doSomething`
 <5> using the method pointer with an `Integer` calls the `Integer` version of `doSomething`
 
+[[method-reference-operator]]
+=== Method reference operator
+
+The Parrot parser in Groovy 3+ supports the Java 8+ method reference operator.
+The method reference operator (`::`) can be used to reference a method or constructor
+in contexts expecting a functional interface. This overlaps somewhat with the functionality
+provided by Groovy's method pointer operator. Indeed, for dynamic Groovy, the method
+reference operator is just an alias for the method pointer operator.
+For static Groovy, the operator results in bytecode similar to the bytecode
+that Java would produce for the same context.
+
+Some examples highlighting various supported method reference cases are shown in the following script:
+
+[source,groovy]
+----
+include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=method_refs,indent=0]
+----
+<1> class instance method reference: add(BigInteger val) is an instance method in BigInteger
+<2> object instance method reference: add(BigInteger val) is an instance method for object 3G
+<3> class static method reference: valueOf(long val) is a static method for class BigInteger
+<4> object static method reference: valueOf(long val) is a static method for object 3G (some consider this bad style in normal circumstances)
+
+Some examples highlighting various supported constructor reference cases are shown in the following script:
+
+[source,groovy]
+----
+include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=constructor_refs,indent=0]
+----
+<1> class constructor reference
+<2> array constructor reference
+
 == Regular expression operators
 
 === Pattern operator
diff --git a/src/spec/test/OperatorsTest.groovy b/src/spec/test/OperatorsTest.groovy
index d4d34ee..ca0831b 100644
--- a/src/spec/test/OperatorsTest.groovy
+++ b/src/spec/test/OperatorsTest.groovy
@@ -237,13 +237,13 @@ assert user.@name == 'Bob'                   // <1>
 '''
     }
 
-    void testMethodReference() {
-        // tag::method_reference[]
+    void testMethodPointer() {
+        // tag::method_pointer[]
         def str = 'example of method reference'            // <1>
         def fun = str.&toUpperCase                         // <2>
         def upper = fun()                                  // <3>
         assert upper == str.toUpperCase()                  // <4>
-        // end::method_reference[]
+        // end::method_pointer[]
         assert fun instanceof Closure
 
         assertScript '''
@@ -251,7 +251,7 @@ assert user.@name == 'Bob'                   // <1>
                 String name
                 int age
             }
-            // tag::method_reference_strategy[]
+            // tag::method_pointer_strategy[]
             def transform(List elements, Closure action) {                    // <1>
                 def result = []
                 elements.each {
@@ -268,17 +268,51 @@ assert user.@name == 'Bob'                   // <1>
                 new Person(name: 'Julia', age: 35)]                           // <4>
             assert transform(list, action) == ['Bob is 42', 'Julia is 35']    // <5>
 
-            // end::method_reference_strategy[]
+            // end::method_pointer_strategy[]
         '''
 
         assertScript '''
-            // tag::method_reference_dispatch[]
+            // tag::method_pointer_dispatch[]
             def doSomething(String str) { str.toUpperCase() }    // <1>
             def doSomething(Integer x) { 2*x }                   // <2>
             def reference = this.&doSomething                    // <3>
             assert reference('foo') == 'FOO'                     // <4>
             assert reference(123)   == 246                       // <5>
-            // end::method_reference_dispatch[]
+            // end::method_pointer_dispatch[]
+        '''
+    }
+
+    void testMethodReference() {
+        assertScript '''
+            // tag::method_refs[]
+            import groovy.transform.CompileStatic
+            import static java.util.stream.Collectors.toList
+
+            @CompileStatic
+            void methodRefs() {
+                assert 6G == [1G, 2G, 3G].stream().reduce(0G, BigInteger::add)                           // <1>
+
+                assert [4G, 5G, 6G] == [1G, 2G, 3G].stream().map(3G::add).collect(toList())              // <2>
+
+                assert [1G, 2G, 3G] == [1L, 2L, 3L].stream().map(BigInteger::valueOf).collect(toList())  // <3>
+
+                assert [1G, 2G, 3G] == [1L, 2L, 3L].stream().map(3G::valueOf).collect(toList())          // <4>
+            }
+
+            methodRefs()
+            // end::method_refs[]
+            // tag::constructor_refs[]
+            @CompileStatic
+            void constructorRefs() {
+                assert [1, 2, 3] == ['1', '2', '3'].stream().map(Integer::new).collect(toList())  // <1>
+
+                def result = [1, 2, 3].stream().toArray(Integer[]::new)                           // <2>
+                assert result instanceof Integer[]
+                assert result.toString() == '[1, 2, 3]'
+            }
+
+            constructorRefs()
+            // end::constructor_refs[]
         '''
     }
 
diff --git a/src/test/groovy/transform/stc/MethodReferenceTest.groovy b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
index 4adc4b4..3a3f3ab 100644
--- a/src/test/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/transform/stc/MethodReferenceTest.groovy
@@ -21,6 +21,7 @@ package groovy.transform.stc
 class MethodReferenceTest extends GroovyTestCase {
     // class::instanceMethod
     void testFunctionCI() {
+        // TODO can this be removed on JDK12
         if (true) return
 
         assertScript '''
@@ -55,16 +56,15 @@ class MethodReferenceTest extends GroovyTestCase {
 
     // class::instanceMethod
     void testBinaryOperatorCI() {
+        // TODO can this be removed on JDK12
         if (true) return
 
         assertScript '''
-            import java.util.stream.Stream
-
             @groovy.transform.CompileStatic
             void p() {
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), BigDecimal::add)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, BigDecimal::add)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
@@ -74,7 +74,6 @@ class MethodReferenceTest extends GroovyTestCase {
     // class::staticMethod
     void testFunctionCS() {
         assertScript '''
-            import java.util.stream.Stream
             import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
@@ -91,23 +90,20 @@ class MethodReferenceTest extends GroovyTestCase {
     // instance::instanceMethod
     void testBinaryOperatorII() {
         assertScript '''
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
-
             @groovy.transform.CompileStatic
             void p() {
                 Adder adder = new Adder()
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), adder::add)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
             
             @groovy.transform.CompileStatic
             class Adder {
-                public BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
             }
         '''
@@ -116,14 +112,11 @@ class MethodReferenceTest extends GroovyTestCase {
     // expression::instanceMethod
     void testBinaryOperatorII_EXPRESSION() {
         assertScript '''
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
-
             @groovy.transform.CompileStatic
             void p() {
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), new Adder()::add)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder()::add)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
@@ -131,7 +124,7 @@ class MethodReferenceTest extends GroovyTestCase {
             @groovy.transform.CompileStatic
             class Adder {
                 public BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                    a.add(b)
                 }
             }
         '''
@@ -140,12 +133,9 @@ class MethodReferenceTest extends GroovyTestCase {
     // expression::instanceMethod
     void testBinaryOperatorII_EXPRESSION2() {
         assertScript '''
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
-
             @groovy.transform.CompileStatic
             void p() {
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), new Adder().getThis()::add)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder().getThis()::add)
 
                 assert new BigDecimal(6) == result
             }
@@ -154,8 +144,8 @@ class MethodReferenceTest extends GroovyTestCase {
             
             @groovy.transform.CompileStatic
             class Adder {
-                public BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
                 
                 Adder getThis() {
@@ -168,23 +158,20 @@ class MethodReferenceTest extends GroovyTestCase {
     // instance::staticMethod
     void testBinaryOperatorIS() {
         assertScript '''
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
-
             @groovy.transform.CompileStatic
             void p() {
                 Adder adder = new Adder()
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), adder::add)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, adder::add)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
             
             @groovy.transform.CompileStatic
             class Adder {
-                public static BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                static BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
             }
         '''
@@ -193,22 +180,19 @@ class MethodReferenceTest extends GroovyTestCase {
     // expression::staticMethod
     void testBinaryOperatorIS_EXPRESSION() {
         assertScript '''
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
-
             @groovy.transform.CompileStatic
             void p() {
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), new Adder()::add)
+                def result = [2.0G, 2.0G, 3.0G].stream().reduce(0.0G, new Adder()::add)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
             
             @groovy.transform.CompileStatic
             class Adder {
-                public static BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                static BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
             }
         '''
@@ -217,26 +201,23 @@ class MethodReferenceTest extends GroovyTestCase {
     // expression::staticMethod
     void testBinaryOperatorIS_EXPRESSION2() {
         assertScript '''
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
-
             @groovy.transform.CompileStatic
             void p() {
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), Adder.newInstance()::add)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, Adder.newInstance()::add)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
             
             @groovy.transform.CompileStatic
             class Adder {
-                public static BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                static BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
                 
                 static Adder newInstance() {
-                    return new Adder()
+                    new Adder()
                 }
             }
         '''
@@ -245,8 +226,6 @@ class MethodReferenceTest extends GroovyTestCase {
     // arrayClass::new
     void testIntFunctionCN() {
         assertScript '''
-            import java.util.stream.Stream
-
             @groovy.transform.CompileStatic
             void p() {
                 assert new Integer[] { 1, 2, 3 } == [1, 2, 3].stream().toArray(Integer[]::new)
@@ -260,7 +239,6 @@ class MethodReferenceTest extends GroovyTestCase {
     // class::new
     void testFunctionCN() {
         assertScript '''
-            import java.util.stream.Stream
             import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
@@ -277,7 +255,6 @@ class MethodReferenceTest extends GroovyTestCase {
     void testFunctionCS_RHS() {
         assertScript '''
             import java.util.function.Function
-            import java.util.stream.Stream
             import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
@@ -295,8 +272,6 @@ class MethodReferenceTest extends GroovyTestCase {
     // class::staticMethod
     void testFunctionCS_RHS_NOTYPE() {
         assertScript '''
-            import java.util.function.Function
-            import java.util.stream.Stream
             import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
@@ -315,24 +290,22 @@ class MethodReferenceTest extends GroovyTestCase {
     void testBinaryOperatorII_RHS() {
         assertScript '''
             import java.util.function.BinaryOperator
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
             void p() {
                 Adder adder = new Adder()
                 BinaryOperator<BigDecimal> b = adder::add
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), b)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, b)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
             
             @groovy.transform.CompileStatic
             class Adder {
-                public BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
             }
         '''
@@ -342,23 +315,21 @@ class MethodReferenceTest extends GroovyTestCase {
     void testBinaryOperatorII_RHS2() {
         assertScript '''
             import java.util.function.BinaryOperator
-            import java.util.stream.Stream
-            import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
             void p() {
                 BinaryOperator<BigDecimal> b = new Adder()::add
-                def result = [new BigDecimal(1), new BigDecimal(2), new BigDecimal(3)].stream().reduce(new BigDecimal(0), b)
+                def result = [1.0G, 2.0G, 3.0G].stream().reduce(0.0G, b)
 
-                assert new BigDecimal(6) == result
+                assert 6.0G == result
             }
             
             p()
             
             @groovy.transform.CompileStatic
             class Adder {
-                public BigDecimal add(BigDecimal a, BigDecimal b) {
-                    return a.add(b)
+                BigDecimal add(BigDecimal a, BigDecimal b) {
+                    a.add(b)
                 }
             }
         '''
@@ -368,7 +339,6 @@ class MethodReferenceTest extends GroovyTestCase {
     void testFunctionCN_RHS() {
         assertScript '''
             import java.util.function.Function
-            import java.util.stream.Stream
             import java.util.stream.Collectors
 
             @groovy.transform.CompileStatic
@@ -378,7 +348,6 @@ class MethodReferenceTest extends GroovyTestCase {
             }
             
             p()
-
         '''
     }
 
@@ -395,7 +364,6 @@ class MethodReferenceTest extends GroovyTestCase {
             }
             
             p()
-
         '''
     }
 }