Это четвертая часть в серии постов в блоге (читай часть 1 , часть 2 и часть 3 ), в которой приводятся некоторые практические примеры лямбд, как может выглядеть функциональное программирование на Java и как лямбды могут влиять на некоторые из известных библиотек Java земельные участки. В этой части кратко описываются изменения нового предложения, которое было опубликовано во время написания этой серии, и как оно меняет некоторые примеры из этой серии.
Новое предложение На
прошлой неделе Брайан Гетц опубликовал новое предложениедобавить лямбда-выражения в Java, основанные на предыдущем предложении straw-man. Два самых больших изменения заключаются в том, что типы функций были удалены и что будет больше выводов типов, чем раньше. Также в новом предложении используется другой синтаксис для лямбда-выражений, но в нем также говорится, что это не отражает окончательное решение по синтаксису. Но давайте кратко рассмотрим каждый из этих пунктов.
Нет больше типов функций
Сначала это звучит раздражающе. Без типов функций, как мы могли бы передавать функции другим методам или функциям? Нам нужно как-то объявить их как параметры. Ответ заключается в том, что функции или лучшие лямбда-выражения должны быть преобразованы в типы SAM. Помните, что типы SAM являются отдельными типами абстрактных методов, такими как интерфейсы только с одним методом или абстрактные классы только с одним абстрактным методом, и что лямбда-выражения могут автоматически преобразовываться в такие типы. Это называется преобразованием SAM, которое я также обсуждал в первой части этой серии.
Таким образом, функциональные типы будут в первую очередь заменены преобразованием SAM, лямбда-выражения могут появляться только в тех местах, где они могут быть преобразованы в тип SAM. Я не до конца понимаю причины этого решения, но в некотором смысле оно действительно имеет смысл. Как кратко упомянуто в первой части этой серии, с точки зрения разработчика API вам больше не нужно ломать голову, если ваши методы должны принимать тип функции или тип SAM в качестве аргумента. И в любом случае типы SAM, вероятно, окажутся более гибкими.
Однако это изменит почти все примеры из этой серии. Во всех местах, где метод принимал функцию в качестве аргумента, тип этого аргумента должен быть изменен на тип SAM, и я почти везде использовал типы функций. Мы рассмотрим это позже и посмотрим, имеет ли смысл сейчас иметь некоторые универсальные интерфейсы функций для таких функций, как Function <X, Y>.
Больше выводов типов
Как мы также видели в примерах этой серии, лямбда-выражения могут быть довольно многословными из-за объявлений типов. Новое предложение гласит, что в основном все типы в лямбда-выражениях могут быть определены компилятором — их возвращаемые типы, типы параметров и типы исключений. Это сделает лямбды намного более читабельными.
Альтернативный синтаксис
Как уже говорилось, синтаксис нового предложения не отражает окончательное решение, но он гораздо больше похож на Scala или Groovy в этом предложении.
Хотя мне лично этот синтаксис стрелок нравится гораздо лучше, я буду придерживаться # -синтаксиса в этой серии, потому что его использует прототип.
Дополнительные изменения
Просто для полноты, предложение содержит еще несколько изменений. эта функция в лямбдах имеет семантику, отличную от предыдущей, в лямбдах нельзя использовать break и continue, и вместо return yield будет использоваться для возврата значений из лямбда-выражения (нет подробностей о том, как точно работает yield). Также будут ссылки на методы, которые позволяют ссылаться на методы существующего класса или экземпляра объекта.
Влияние на примеры
Теперь давайте посмотрим, как новое предложение меняет некоторые примеры предыдущих постов. Пример фильтрации файлов из первой части выглядел так:
Код клиента выглядел так:
Поскольку больше не будет типов функций, нам придется изменить fileFilter, чтобы он принимал тип SAM вместо типа функции. В этом случае все просто, мы могли бы просто изменить тип второго аргумента на FileFilter и вызвать его метод accept ():
хотя клиентская сторона все та же.
Теперь, как вы могли заметить (или вспомнить из части 2), это довольно плохой пример, потому что на самом деле уже есть метод File.listFiles (FileFilter), который мы также можем вызвать с помощью лямбды:
лямбда будет преобразована в FileFilter автоматически в этом случае. Но несмотря на то, что метод fileFilter является плохим примером, он довольно хорошо показывает, что удаление типов функций имеет очень небольшое влияние, если уже существует соответствующий тип SAM.
Прежде чем мы продолжим, вот клиентская сторона с синтаксисом стрелки и выводом типа:
Теперь давайте посмотрим, как удаление типов функций меняет примеры в отсутствие соответствующего типа SAM. Для этого здесь снова используется функция List <T> .map из части 3:
нам нужно заменить аргумент типа функции f на тип SAM. Мы могли бы начать с написания интерфейса Mapper с единственной картой методов. Это был бы интерфейс, особенно для использования с функцией карты. Но имея в виду, что, вероятно, существует намного больше функций, похожих на нашу функцию карты, мы могли бы создать более общий интерфейс Function или, более конкретно, интерфейс Function1 <X1, Y>, который представляет функцию, которая принимает ровно один аргумент типа X1 и возвращает значение типа Y.
При этом мы могли бы изменить нашу функцию отображения, приняв Function1 вместо аргумента типа функции:
опять же, клиентская сторона все равно будет прежней. Лямбда-выражение будет преобразовано в Function1.
Другие примеры в основном те же самые, поэтому я думаю, что этого достаточно, чтобы показать изменения, внесенные новым предложением путем удаления типов функций.
Наконец, давайте кратко рассмотрим новый синтаксис и вывод более сильного типа. При первоначальном предложении метод File.eachLine может быть вызван следующим образом (см. Также часть 2).
Это будет выглядеть примерно так с синтаксисом нового предложения:
И с каким — то более синтаксическим сахаром, например , если оно было разрешено удалять скобки, оставить оттуда Лямбды аргумент , если он просто принимает один аргумент и назвать это его в этом случае, то это будет выглядеть еще более похожее на структуру управления заводным:
Но это пока не является частью какого-либо предложения.
Подводя итог, можно сказать, что удаление типов функций не оказывает такого большого влияния на примеры, и в некотором смысле устраняет сложность и выглядит более похожим на Java. Для меня было бы вполне разумно иметь универсальные типы функций SAM в стандартных библиотеках, например, Function0 для функции, которая не принимает аргументов, Function1 для функции, которая принимает один аргумент и т. Д. (До Function23, тогда Java будет иметь более Скала, ууу!). Дальнейшая сложность устраняется более сильными возможностями вывода типа.
От http://stronglytypedblog.blogspot.com/2010/07/lambdas-in-java-preview-part-4-proposal.html