Можно ли считать "вызов по имени" в Scala синтаксическим сахаром API функционального интерфейса Java8?
Пример Scala "call be name":def giveMeName(b: => String)
javap
результат:
public class some.package.CallByNameEx {
public void giveMeName(scala.Function0<java.lang.String>);
public some.package.CallByNameEx();
}
Пример API функционального интерфейса Java:void giveMeName(Supplier<String> b)
javap
результат:
public class some.package.SupplyEx {
public some.package.SupplyEx();
void giveMeName(java.util.function.Supplier<java.lang.String>);
}
Есть ли существенная разница в том, как они оцениваются внутренне, учитывая javap
Результат обоих приведенных выше случаев был практически одинаковым
Согласно моему нынешнему пониманию, они оба используют замыкания и лениво оценивают выражение. Пожалуйста, поправьте меня, если понимание неверно.
2 ответа
Вы правильно поняли, call-by-name
синтаксис в значительной степени является сокращением, позволяющим вам избежать дополнительной бюрократии, связанной с передачей Function0
вокруг.
Внутренне b: => String
будет представлен Function0
- как b: () => String
было бы.
Разница в том, что с помощью call-by-name
, вы можете просто игнорировать детали реализации использования Function0
,
Посмотрим, как это будет выглядеть с b: () => String
:
def giveMeName(b: () => String): String = b.apply()
и то же самое снова с помощью call-by-name
:
def giveMeName(b: => String): String = b
Обратите внимание на то, как красиво шаблон apply()
звонка можно избежать.
Таким образом, это синтаксический сахар, но не для функциональных интерфейсов Java, а для нативного Scala Function0
Я написал немного больше об этом здесь: http://4comprehension.com/leveraging-lambda-expressions-for-lazy-evaluation-in-java/
Можно ли считать это синтаксическим сахаром? Да, возможно. API функционального интерфейса Java8? Нет.
Давайте перейдем к определению в http://wiki.c2.com/?SyntacticSugar:
Функции, добавленные в язык или другой формализм, чтобы сделать его более приятным для людей, но которые не влияют на выразительность формализма (сравните хром). Используется ESP. когда есть очевидный и тривиальный перевод сахарного признака в другие конструкции, уже присутствующие в обозначениях.
Таким образом, функции Scala могут быть синтаксическим сахаром только для других функций Scala, но не для Java. В этом случае, def giveMeName(b: => String)
переводится что-то вроде в def giveMeName(b: () => String)
, "Возможно" часть заключается в том, что перевода декларации недостаточно: необходимо также перевести все вызовы, а метод помечен, чтобы вы не могли передать что-то типа () => String
в def giveMeName(b: => String)
,
Есть ли существенное различие в том, как они оцениваются внутренне, учитывая, что результаты javap в обоих вышеупомянутых случаях были практически идентичными
В результате вы показываете, что нечего оценивать, и они все равно будут "почти идентичными", если вы замените Supplier<String>
от List<String>
, Означает ли это, что вызов по имени является синтаксическим сахаром для List
? Конечно, нет.
Но Скала () => String
семантически эквивалентно Supplier<String>
(это не то, что вы можете увидеть из javap), и потому что => String
эквивалентно () => String
они оба используют замыкания и лениво оценивают выражение
Если "они" - это API-интерфейсы, которые вы показываете, нет, ни сами не используйте замыкания. Вы можете передавать замыкания обоим (или не замыканиям).