I am struggling to comprehend why code which in Java works, then fails in groovy. For example:
I've found that if I use Tuple2.of(...
I will get a compilation error, but new Tuple2(..
works. Why?
static Stream<Tuple2<LocalDate, Double>> forecastEachMonth(Tuple2<LocalDate, Double> openingBalance, Double rate){
Stream<Tuple2<LocalDate, Double>> stream = Stream.iterate(
openingBalance,
{
LocalDate current = it.first
LocalDate nextDate = it.first.plusMonths(1)
int days = Days.daysBetween(current, nextDate).days
double years = days / 365.0
double interest = it.second * rate * years
double nextBalance = it.second interest
// return Tuple2.of(nextDate, nextBalance) // exception after 2 iterations, Have no idea why.
return new Tuple2(nextDate, nextBalance)
}
)
return stream
}
You can test this out:
Stream<Tuple2<LocalDate,Double>> test = forecastEachMonth(
LocalDate.now(),
200000.0d,
0.05d
)
println test.limit(200).collect(Collectors.toList())
Gives an error:
Expected earlier checking to detect generics parameter arity mismatch
Expected: groovy.lang.Tuple<E>
Supplied: groovy.lang.Tuple<org.joda.time.LocalDate,java.lang.Double>
But Intellij knows the correct type when I hover over the local variable.
I've also converted the project to Java and it just works. Which severely plagues my experience coding in Groovy, as I lose heaps of time on code which works in Java but not in Groovy. (Albeit there is no Tuple in Java I just used another library having the collection Pair). But I just can't get my head around why Groovy suddenly doesn't know the type of a given variable, reverts to Object, then just throws an exception, how is that desirable?
CodePudding user response:
can't understand your "java" pain.
the following code sample works well even with compile static:
@groovy.transform.CompileStatic
def f(){
Tuple2<Date, Double> a = new Tuple2(new Date(), 1)
Tuple2<Date, Double> b = new Tuple2(new Date(), 2)
List<Tuple2<Date, Double>> list = [a,b]
List<Tuple2<Date, Double>> result = list.takeWhile{Tuple2<Date, Double> e-> e.getV2()<2}
assert result instanceof List
assert result.size()==1
assert result[0].getV2()<2
assert result[0] instanceof Tuple2
}
f()
your questions:
I've found that if I use
Tuple2.of(...
I will get a compilation error, butnew Tuple2(..
works. Why?
there is not such method Tuple2.of(...
in Tuple2 class
why Groovy suddenly doesn't know the type of a given variable, reverts to Object, then just throws an exception, how is that desirable?
i used your code with minimal changes to make it runnable and it works without any error:
import java.time.*
import java.util.stream.*
static Stream<Tuple2<LocalDate, Double>> forecastEachMonth(Tuple2<LocalDate, Double> openingBalance, Double rate){
Stream<Tuple2<LocalDate, Double>> stream = Stream.iterate(
openingBalance,
{
LocalDate current = it.first
LocalDate nextDate = it.first.plusMonths(1)
int days = nextDate - current
double years = days / 365.0
double interest = it.second * rate * years
double nextBalance = it.second interest
return new Tuple2(nextDate, nextBalance)
}
)
return stream
}
Stream<Tuple2<LocalDate,Double>> test = forecastEachMonth(
new Tuple2(LocalDate.now(),200000.0d),
0.05d
)
println test.limit(200).collect(Collectors.toList())