Home > other >  I just can't understand Groovy types with Java mindset
I just can't understand Groovy types with Java mindset

Time:12-13

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, but new 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())
  • Related