Я изо всех сил пытаюсь понять, почему код, который работает на Java, не работает в groovy. Например:
Я обнаружил, что если я использую Tuple2.of(...
, я получу ошибку компиляции, но new Tuple2(..
работает. Почему?
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
}
Вы можете проверить это:
Stream<Tuple2<LocalDate,Double>> test = forecastEachMonth(
LocalDate.now(),
200000.0d,
0.05d
)
println test.limit(200).collect(Collectors.toList())
Выдает ошибку:
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>
Но Intellij знает правильный тип, когда я навожу курсор на локальную переменную.
Я также преобразовал проект в Java, и он просто работает. Что серьезно мешает моему опыту кодирования в Groovy, так как я теряю кучу времени на код, который работает на Java, но не на Groovy. (Хотя в Java нет кортежа, я просто использовал другую библиотеку с коллекцией Pair). Но я просто не могу понять, почему Groovy вдруг не знает тип данной переменной, возвращается к Object, а затем просто выдает исключение, как это желательно?
«Я обнаружил, что если я использую Tuple2.of(..., я получу ошибку компиляции» — было бы хорошо знать, что такое ошибка компиляции и откуда вы ожидаете, что этот метод будет исходить.
Пожалуйста, смотрите обновление, если необходимо, обратите внимание, хотя версия Java не имеет Tuple, но проблема больше в том, что я не ожидаю, что семантика, подобная этой, полностью разрушит мой код, а затем будет стоить мне кучу времени на отслеживание проблемы. Я хотел бы понять, почему Groovy делает то, что делает.
Где вы нашли метод Type2.of? В groovy doc такого метода нет...
не могу понять вашу "джавскую" боль.
следующий пример кода хорошо работает даже со статической компиляцией:
@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()
Я обнаружил, что если я использую
Tuple2.of(...
, я получу ошибку компиляции, ноnew Tuple2(..
работает. Почему?
такого метода нет Tuple2.of(...
в классе Tuple2
почему Groovy внезапно не знает тип данной переменной, возвращается к Object, а затем просто выдает исключение, как это желательно?
я использовал ваш код с минимальными изменениями, чтобы сделать его работоспособным, и он работает без ошибок:
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())
Я обновил, теперь вы увидите, что если вы запустите мой метод, вы обнаружите, что it
переходит от кортежа к объекту. Хотелось бы знать, почему. Обратите внимание, что здесь я использую Jodatime.
Метод создает поток будущей стоимости банковских счетов каждый месяц с учетом процентной ставки с ежемесячным начислением процентов, надеюсь, имеет смысл.
попробовал ваш код - работает хорошо
Вам нужно изменить возврат на: return Tuple2.of(nextDate, nextBalance)
Вы обнаружите ошибки после второй итерации.
у меня ошибка на первой итерации: groovy.lang.MissingMethodException: No signature of method: static groovy.lang.Tuple2.of() is applicable for argument types: (java.time.LocalDate, Double) values: [2023-01-10, 200849.315068]
. какое сообщение об ошибке вы видите? опять же - функции Tuple2.of()
нет, однако ее можно определить в какой-нибудь библиотеке вот так: Tuple2.metaClass.static.of = {a,b-> new Tuple2(a,b)}
.
Хорошо, @daggett, я знаю, в чем была проблема. Tuple расширяет AbstractList, реализует List, в котором есть метод of
. Таким образом, у Tuple также есть этот метод. Это подпись <E> List<E> of(E e1, E e2)
, поэтому, если ваши аргументы разных типов, вы получите ошибку компиляции, у меня не было @TypeChecked
. Хорошо, чтобы отследить проблему, но я в конечном итоге отказался от groovym, у меня действительно нет времени отслеживать этот материал, когда это происходит.
Вот почему я спросил вас о версии java/groovy. Но ты проигнорил)
Прости Даггет! Я приму ваш ответ и проголосую за вас, за усилия, продолжайте в том же духе, ха-ха. Но да, я действительно не получил прироста производительности с Groovy, возможно, попробую еще раз в будущем, но на данный момент без IDE я борюсь.
Какая версия groovy+java?