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()
-
'''
}
}