Skip to content

Commit

Permalink
Initial implementation of new For() constructs (#1629) (#2281)
Browse files Browse the repository at this point in the history
  • Loading branch information
CauchyPeano authored and danieldietrich committed Aug 4, 2018
1 parent e01b510 commit 161e162
Show file tree
Hide file tree
Showing 4 changed files with 2,132 additions and 395 deletions.
4 changes: 2 additions & 2 deletions vavr-benchmark/src/test/java/io/vavr/idiom/ForBenchmark.java
Expand Up @@ -59,13 +59,13 @@ public static void main(String... args) {
public static class Base {
int CONTAINER_SIZE = 1000;
int AGGREGATE;
List<Integer> ELEMENTS;
io.vavr.collection.List<Integer> ELEMENTS;

final BiFunction<Integer, Integer, Integer> AGGREGATOR = (i, j) -> i ^ j;

@Setup
public void setup() {
ELEMENTS = Arrays.asList(getRandomValues(CONTAINER_SIZE, 0, true));
ELEMENTS = io.vavr.collection.List.ofAll(Arrays.stream(getRandomValues(CONTAINER_SIZE, 0, true)));

AGGREGATE = 0;
for (Integer i : ELEMENTS) {
Expand Down
67 changes: 46 additions & 21 deletions vavr/generator/Generator.scala
Expand Up @@ -100,6 +100,8 @@ def generateMainClasses(): Unit = {
val PredicateType = im.getType("java.util.function.Predicate")
val SupplierType = im.getType("java.util.function.Supplier")

val monadicTypesFor = List(OptionType, FutureType, TryType, ListType)

def genTraversableAliases(traversableType: String, returnType: String, name: String) = xs"""
// -- $name

Expand Down Expand Up @@ -709,24 +711,24 @@ def generateMainClasses(): Unit = {
return $IteratorType.ofAll(ts).flatMap(f);
}

${(1 to N).gen(i => {
${monadicTypesFor.gen(mtype => (1 to N).gen(i => {
val generics = (1 to i).gen(j => s"T$j")(", ")
val params = (1 to i).gen(j => s"Iterable<T$j> ts$j")(", ")
val params = (1 to i).gen(j => s"$mtype<T$j> ts$j")(", ")
xs"""
/$javadoc
* Creates a {@code For}-comprehension of ${i.numerus("Iterable")}.
${(0 to i).gen(j => if (j == 0) "*" else s"* @param ts$j the ${j.ordinal} Iterable")("\n")}
${(1 to i).gen(j => s"* @param <T$j> component type of the ${j.ordinal} Iterable")("\n")}
* Creates a {@code For}-comprehension of ${i.numerus(mtype)}.
${(0 to i).gen(j => if (j == 0) "*" else s"* @param ts$j the ${j.ordinal} $mtype")("\n")}
${(1 to i).gen(j => s"* @param <T$j> component type of the ${j.ordinal} $mtype")("\n")}
* @return a new {@code For}-comprehension of arity $i
*/
public static <$generics> For$i<$generics> For($params) {
public static <$generics> For$i$mtype<$generics> For($params) {
${(1 to i).gen(j => xs"""$Objects.requireNonNull(ts$j, "ts$j is null");""")("\n")}
return new For$i<>(${(1 to i).gen(j => s"ts$j")(", ")});
return new For$i$mtype<>(${(1 to i).gen(j => s"ts$j")(", ")});
}
"""
})("\n\n")}
})("\n\n"))("\n\n")}

${(1 to N).gen(i => {
${monadicTypesFor.gen(mtype => (1 to N).gen(i => {
val generics = (1 to i).gen(j => s"T$j")(", ")
val functionType = i match {
case 1 => FunctionType
Expand All @@ -736,13 +738,13 @@ def generateMainClasses(): Unit = {
val args = (1 to i).gen(j => s"? super T$j")(", ")
xs"""
/$javadoc
* For-comprehension with ${i.numerus("Iterable")}.
* For-comprehension with ${i.numerus(IteratorType)}.
*/
public static class For$i<$generics> {
public static class For$i$mtype<$generics> {

${(1 to i).gen(j => xs"""private final Iterable<T$j> ts$j;""")("\n")}
${(1 to i).gen(j => xs"""private final $mtype<T$j> ts$j;""")("\n")}

private For$i(${(1 to i).gen(j => s"Iterable<T$j> ts$j")(", ")}) {
private For$i$mtype(${(1 to i).gen(j => s"$mtype<T$j> ts$j")(", ")}) {
${(1 to i).gen(j => xs"""this.ts$j = ts$j;""")("\n")}
}

Expand All @@ -753,14 +755,14 @@ def generateMainClasses(): Unit = {
* @param <R> type of the resulting {@code Iterator} elements
* @return an {@code Iterator} of mapped results
*/
public <R> $IteratorType<R> yield($functionType<$args, ? extends R> f) {
public <R> $mtype<R> yield($functionType<$args, ? extends R> f) {
$Objects.requireNonNull(f, "f is null");
${if (i == 1) xs"""
return $IteratorType.ofAll(ts1).map(f);
return ts1.map(f);
""" else xs"""
return
${(1 until i).gen(j => s"$IteratorType.ofAll(ts$j).flatMap(t$j ->")("\n")}
$IteratorType.ofAll(ts$i).map(t$i -> f.apply(${(1 to i).gen(j => s"t$j")(", ")}))${")" * (i - 1)};
${(1 until i).gen(j => s"ts$j.flatMap(t$j ->")("\n")}
ts$i.map(t$i -> f.apply(${(1 to i).gen(j => s"t$j")(", ")}))${")" * (i - 1)};
"""}
}

Expand All @@ -770,13 +772,13 @@ def generateMainClasses(): Unit = {
*
* @return an {@code Iterator} of mapped results
*/
public $IteratorType<T1> yield() {
public $mtype<T1> yield() {
return yield(Function.identity());
}
""")}
}
"""
})("\n\n")}
})("\n\n"))("\n\n")}
"""
}

Expand Down Expand Up @@ -2382,6 +2384,9 @@ def generateTestClasses(): Unit = {
val TryType = im.getType("io.vavr.control.Try")
val JavaComparatorType = im.getType("java.util.Comparator")

val monadicTypesFor = List(OptionType)
val monadicFunctionTypesFor = List(FutureType, TryType)

val d = "$"

im.getStatic("io.vavr.API.*")
Expand Down Expand Up @@ -2662,7 +2667,7 @@ def generateTestClasses(): Unit = {

${(1 to N).gen(i => xs"""
@$test
public void shouldIterateFor$i() {
public void shouldIterateFor$ListType$i() {
final $ListType<Integer> result = For(
${(1 to i).gen(j => s"$ListType.of(1, 2, 3)")(",\n")}
).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")}).toList();
Expand All @@ -2672,11 +2677,31 @@ def generateTestClasses(): Unit = {
}
""")("\n\n")}

${monadicTypesFor.gen(mtype => (1 to N).gen(i => { xs"""
@$test
public void shouldIterateFor$mtype$i() {
final $mtype<Integer> result = For(
${(1 to i).gen(j => s"$mtype.of($j)")(",\n")}
).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")});
$assertThat(result.get()).isEqualTo(${(1 to i).sum});
}
"""})("\n\n"))("\n\n")}

${monadicFunctionTypesFor.gen(mtype => (1 to N).gen(i => { xs"""
@$test
public void shouldIterateFor$mtype$i() {
final $mtype<Integer> result = For(
${(1 to i).gen(j => s"$mtype.of(() -> $j)")(",\n")}
).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")});
$assertThat(result.get()).isEqualTo(${(1 to i).sum});
}
"""})("\n\n"))("\n\n")}

@$test
public void shouldIterateNestedFor() {
final $ListType<String> result =
For(${im.getType("java.util.Arrays")}.asList(1, 2), i ->
For(${im.getType("io.vavr.collection.CharSeq")}.of('a', 'b')).yield(c -> i + ":" + c)).toList();
For(${im.getType("io.vavr.collection.List")}.of('a', 'b')).yield(c -> i + ":" + c)).toList();
assertThat(result).isEqualTo($ListType.of("1:a", "1:b", "2:a", "2:b"));
}

Expand Down

0 comments on commit 161e162

Please sign in to comment.