Groovy3: как получить «Java-лямбды» вместо замыканий?

Я провел несколько тестов в Groovy3, и лямбда-выражения Java в основном интерпретируются как замыкания, а не как экземпляры функционального интерфейса. Как я могу заставить лямбды работать с Generics на практике (без принуждения) и как сравнить Groovy4?

@CompileStatic

// lambda (ok!)
Supplier<String> s = 5::toString
// decompiled
Supplier s = DefaultGroovyMethods::toString;

// closure (wth?)
Supplier<String> s
s = 5::toString
// decompiled
Supplier s = null;
Closure var3 = ScriptBytecodeAdapter.getMethodPointer(5, "toString"); 
s = (Supplier)ScriptBytecodeAdapter.castToType(var3, Supplier.class);

// lambda
void test(Supplier<String> s) {}
test(5::toString)
// decompiled
test(DefaultGroovyMethods::toString);

// fails with "Groovyc: The argument is a method reference, 
// but the parameter type is not a functional interface"
<T> void test(T s) {}
this.<Supplier<String>>test(5::toString)

// closure (fails without coercion)
List<Supplier<String>> list = [5::toString]

// lambda (works, but cumbersome)
Supplier<String> s = 5::toString
List<Supplier<String>> list = [s]

// closure (fails without coercion)
List<Supplier<String>> list = []
list.add(5::toString)

Я ожидаю, что статически скомпилированный синтаксис лямбда-выражений Java всегда будет обеспечивать соблюдение семантики лямбда-выражений Java.

Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
1
0
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Лямбды и ссылки на методы — это новая функция Groovy 3. Учитывая это, целью статической компиляции (@CompileStatic) было работать как Java. Однако есть некоторые крайние случаи, которые возникли как ошибки и были исправлены начиная с Groovy 3.0.0, а некоторые — нет. Вы столкнулись с некоторыми из этих крайних случаев.

Когда Groovy не может обнаружить, что целью лямбда-выражения или выражения ссылки на метод является функциональный интерфейс, он прибегает к обработке замыкания или указателя метода соответственно. Вот почему вы видите «ScriptBytecodeAdapter.getMethodPointer» для объявления разделения.

У меня есть исправление ошибки, которое войдет в Groovy 3.0.22 для объявления разделения (см. GROOVY-11363). Этот случай уже должен быть правильно обработан (как и следовало ожидать) в Groovy 4.

Пожалуйста, попробуйте каждый из приведенных выше случаев с последней альфа-версией Groovy 5 (на данный момент наша основная ветка), и если вы обнаружите что-то, что не работает должным образом, откройте новый билет здесь: https://issues .apache.org/jira/projects/GROOVY

Другие вопросы по теме