Skip to content

Commit 6337759

Browse files
committed
New feature: For-comprehensions for Eithers and Validations
1 parent b41ffda commit 6337759

File tree

3 files changed

+1309
-94
lines changed

3 files changed

+1309
-94
lines changed

vavr/generator/Generator.scala

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ def generateMainClasses(): Unit = {
9898
val PredicateType = im.getType("java.util.function.Predicate")
9999
val SupplierType = im.getType("java.util.function.Supplier")
100100

101-
val monadicTypesFor = List("Iterable", OptionType, FutureType, TryType, ListType)
101+
val monadicTypesFor = List("Iterable", OptionType, FutureType, TryType, ListType, EitherType, ValidationType)
102+
val monadicTypesThatNeedParameter = List(EitherType, ValidationType)
102103

103104
def genTraversableAliases(traversableType: String, returnType: String, name: String) = xs"""
104105
// -- $name
@@ -772,12 +773,15 @@ def generateMainClasses(): Unit = {
772773

773774
${monadicTypesFor.gen(mtype => (1 to N).gen(i => {
774775
val forClassName = if (mtype == "Iterable") { s"For$i" } else { s"For$i$mtype" }
775-
val generics = (1 to i).gen(j => s"T$j")(", ")
776-
val params = (1 to i).gen(j => s"$mtype<T$j> ts$j")(", ")
776+
val isComplex = monadicTypesThatNeedParameter.contains(mtype)
777+
val parameterInset = (if (isComplex) {"L, "} else "")
778+
val generics = parameterInset + (1 to i).gen(j => s"T$j")(", ")
779+
val params = (1 to i).gen(j => s"$mtype<${parameterInset}T$j> ts$j")(", ")
777780
xs"""
778781
/$javadoc
779782
* Creates a {@code For}-comprehension of ${i.numerus(mtype)}.
780783
${(0 to i).gen(j => if (j == 0) "*" else s"* @param ts$j the ${j.ordinal} $mtype")("\n")}
784+
${if (isComplex) s"* @param <L> left-hand type of all ${mtype}s\n" else ""}
781785
${(1 to i).gen(j => s"* @param <T$j> component type of the ${j.ordinal} $mtype")("\n")}
782786
* @return a new {@code For}-comprehension of arity $i
783787
*/
@@ -792,7 +796,8 @@ def generateMainClasses(): Unit = {
792796
val rtype = if (mtype == "Iterable") { IteratorType } else { mtype }
793797
val cons: String => String = if (mtype == "Iterable") { m => s"$IteratorType.ofAll($m)" } else { m => m }
794798
val forClassName = if (mtype == "Iterable") { s"For$i" } else { s"For$i$mtype" }
795-
val generics = (1 to i).gen(j => s"T$j")(", ")
799+
val parameterInset = (if (monadicTypesThatNeedParameter.contains(mtype)) { "L, " } else "")
800+
val generics = parameterInset + (1 to i).gen(j => s"T$j")(", ")
796801
val functionType = i match {
797802
case 1 => FunctionType
798803
case 2 => BiFunctionType
@@ -805,20 +810,20 @@ def generateMainClasses(): Unit = {
805810
*/
806811
public static class $forClassName<$generics> {
807812

808-
${(1 to i).gen(j => xs"""private final $mtype<T$j> ts$j;""")("\n")}
813+
${(1 to i).gen(j => xs"""private final $mtype<${parameterInset}T$j> ts$j;""")("\n")}
809814

810-
private $forClassName(${(1 to i).gen(j => s"$mtype<T$j> ts$j")(", ")}) {
815+
private $forClassName(${(1 to i).gen(j => s"$mtype<${parameterInset}T$j> ts$j")(", ")}) {
811816
${(1 to i).gen(j => xs"""this.ts$j = ts$j;""")("\n")}
812817
}
813818

814819
/$javadoc
815-
* Yields a result for elements of the cross product of the underlying ${i.plural(mtype)}.
820+
* Yields a result for elements of the cross-product of the underlying ${i.plural(mtype)}.
816821
*
817-
* @param f a function that maps an element of the cross product to a result
822+
* @param f a function that maps an element of the cross-product to a result
818823
* @param <R> type of the resulting {@code $rtype} elements
819824
* @return an {@code $rtype} of mapped results
820825
*/
821-
public <R> $rtype<R> yield($functionType<$args, ? extends R> f) {
826+
public <R> $rtype<${parameterInset}R> yield($functionType<$args, ? extends R> f) {
822827
$Objects.requireNonNull(f, "f is null");
823828
${if (i == 1) xs"""
824829
return ${cons("ts1")}.map(f);
@@ -835,7 +840,7 @@ def generateMainClasses(): Unit = {
835840
*
836841
* @return an {@code Iterator} of mapped results
837842
*/
838-
public $rtype<T1> yield() {
843+
public $rtype<${parameterInset}T1> yield() {
839844
return this.yield(Function.identity());
840845
}
841846
""")}
@@ -2657,13 +2662,20 @@ def generateTestClasses(): Unit = {
26572662
val SeqType = im.getType("io.vavr.collection.Seq")
26582663
val MapType = im.getType("io.vavr.collection.Map")
26592664
val OptionType = im.getType("io.vavr.control.Option")
2665+
val EitherType = im.getType("io.vavr.control.Either")
2666+
val ValidationType = im.getType("io.vavr.control.Validation")
26602667
val FutureType = im.getType("io.vavr.concurrent.Future")
26612668
val ExecutorsType = im.getType("java.util.concurrent.Executors")
26622669
val ExecutorService = s"$ExecutorsType.newSingleThreadExecutor()"
26632670
val TryType = im.getType("io.vavr.control.Try")
26642671
val JavaComparatorType = im.getType("java.util.Comparator")
26652672

2666-
val monadicTypesFor = List(OptionType)
2673+
val monadicTypesFor = List(OptionType, EitherType, ValidationType)
2674+
val monadicTypeMetadataFor = Map(
2675+
(OptionType -> ("", "of")),
2676+
(EitherType -> ("Object, ", "right")),
2677+
(ValidationType -> ("Object, ", "valid"))
2678+
)
26672679
val monadicFunctionTypesFor = List(FutureType, TryType)
26682680

26692681
val d = "$"
@@ -2952,11 +2964,14 @@ def generateTestClasses(): Unit = {
29522964
}
29532965
""")("\n\n")}
29542966

2955-
${monadicTypesFor.gen(mtype => (1 to N).gen(i => { xs"""
2967+
${monadicTypesFor.gen(mtype => (1 to N).gen(i =>
2968+
val (parameterInset, builderName) = monadicTypeMetadataFor(mtype);
2969+
{ xs"""
2970+
29562971
@$test
29572972
public void shouldIterateFor$mtype$i() {
2958-
final $mtype<Integer> result = For(
2959-
${(1 to i).gen(j => s"$mtype.of($j)")(",\n")}
2973+
final $mtype<${parameterInset}Integer> result = For(
2974+
${(1 to i).gen(j => s"$mtype.${builderName}($j)")(",\n")}
29602975
).yield(${(i > 1).gen("(")}${(1 to i).gen(j => s"i$j")(", ")}${(i > 1).gen(")")} -> ${(1 to i).gen(j => s"i$j")(" + ")});
29612976
$assertThat(result.get()).isEqualTo(${(1 to i).sum});
29622977
}

0 commit comments

Comments
 (0)