что такое замыкание java

Замыкания, функции изнутри

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/closure.

В этой главе мы продолжим рассматривать, как работают переменные, и, как следствие, познакомимся с замыканиями. От глобального объекта мы переходим к работе внутри функций.

Лексическое окружение

Мы будем называть этот объект «лексическое окружение» или просто «объект переменных».

Пример

Посмотрим пример, чтобы лучше понимать, как это работает:

При вызове функции:

До выполнения первой строчки её кода, на стадии инициализации, интерпретатор создаёт пустой объект LexicalEnvironment и заполняет его.

В данном случае туда попадает аргумент name и единственная переменная phrase :

В конце выполнения функции объект с переменными обычно выбрасывается и память очищается. В примерах выше так и происходит. Через некоторое время мы рассмотрим более сложные ситуации, при которых объект с переменными сохраняется и после завершения функции.

Более формальное описание находится в спецификации ECMA-262, секции 10.2-10.5 и 13.

Доступ ко внешним переменным

Из функции мы можем обратиться не только к локальной переменной, но и к внешней:

Это свойство никогда не меняется. Оно всюду следует за функцией, привязывая её, таким образом, к месту своего рождения.

Если переменная не найдена в функции – она будет искаться снаружи.

Именно благодаря этой механике в примере выше alert(userName) выводит внешнюю переменную. На уровне кода это выглядит как поиск во внешней области видимости, вне функции.

Всегда текущее значение

Значение переменной из внешней области берётся всегда текущее. Оно может быть уже не то, что было на момент создания функции.

Например, в коде ниже функция sayHi берёт phrase из внешней области:

Это естественно, ведь для доступа к внешней переменной функция по ссылке [[Scope]] обращается во внешний объект переменных и берёт то значение, которое там есть на момент обращения.

Вложенные функции

Внутри функции можно объявлять не только локальные переменные, но и другие функции.

К примеру, вложенная функция может помочь лучше организовать код:

Вложенные функции получают [[Scope]] так же, как и глобальные. В нашем случае:

Заметим, что если переменная не найдена во внешнем объекте переменных, то она ищется в ещё более внешнем (через [[Scope]] внешней функции), то есть, такой пример тоже будет работать:

Возврат функции

Рассмотрим более «продвинутый» вариант, при котором внутри одной функции создаётся другая и возвращается в качестве результата.

В разработке интерфейсов это совершенно стандартный приём, функция затем может назначаться как обработчик действий посетителя.

Здесь мы будем создавать функцию-счётчик, которая считает свои вызовы и возвращает их текущее число.

В примере ниже makeCounter создаёт такую функцию:

Если подробнее описать происходящее:

На этом создание «счётчика» завершено.

Возвращённая из makeCounter() функция counter помнит (через [[Scope]] ) о том, в каком окружении была создана.

Это и используется для хранения текущего значения счётчика.

Далее, когда-нибудь, функция counter будет вызвана. Мы не знаем, когда это произойдёт. Может быть, прямо сейчас, но, вообще говоря, совсем не факт.

Переменную во внешней области видимости можно не только читать, но и изменять.

В примере выше было создано несколько счётчиков. Все они взаимно независимы:

Свойства функции

Функция в JavaScript является объектом, поэтому можно присваивать свойства прямо к ней, вот так:

Свойства функции не стоит путать с переменными и параметрами. Они совершенно никак не связаны. Переменные доступны только внутри функции, они создаются в процессе её выполнения. Это – использование функции «как функции».

А свойство у функции – доступно отовсюду и всегда. Это – использование функции «как объекта».

Если хочется привязать значение к функции, то можно им воспользоваться вместо внешних переменных.

В качестве демонстрации, перепишем пример со счётчиком:

При запуске пример работает также.

Принципиальная разница – во внутренней механике и в том, что свойство функции, в отличие от переменной из замыкания – общедоступно, к нему имеет доступ любой, у кого есть объект функции.

Например, можно взять и поменять счётчик из внешнего кода:

Иногда свойства, привязанные к функции, называют «статическими переменными».

В некоторых языках программирования можно объявлять переменную, которая сохраняет значение между вызовами функции. В JavaScript ближайший аналог – такое вот свойство функции.

Итого: замыкания

Замыкание – это функция вместе со всеми внешними переменными, которые ей доступны.

Таково стандартное определение, которое есть в Wikipedia и большинстве серьёзных источников по программированию. То есть, замыкание – это функция + внешние переменные.

Тем не менее, в JavaScript есть небольшая терминологическая особенность.

Обычно, говоря «замыкание функции», подразумевают не саму эту функцию, а именно внешние переменные.

Иногда говорят «переменная берётся из замыкания». Это означает – из внешнего объекта переменных.

Иногда говорят «Вася молодец, понимает замыкания!». Что это такое – «понимать замыкания», какой смысл обычно вкладывают в эти слова?

«Понимать замыкания» в JavaScript означает понимать следующие вещи:

В следующих главах мы углубим это понимание дополнительными примерами, а также рассмотрим, что происходит с памятью.

Источник

Лямбда-выражения Java 8 — это замыкания?

Развернутый ответ на вопрос, вынесенный в заглавие поста, приводится в статье Брюса Эккеля в редакции от 25 ноября 2015 года. Мы решили разместить здесь перевод этой статьи и поинтересоваться, что вы думаете о функциональном программировании в Java, а также об актуальности такой книги:

что такое замыкание java. Смотреть фото что такое замыкание java. Смотреть картинку что такое замыкание java. Картинка про что такое замыкание java. Фото что такое замыкание java

Если кратко – конечно да.

Чтобы дать более развернутый ответ, давайте все-таки разберемся: а зачем мы с ними работаем?

В сущности, лямбда-выражения нужны потому, что они описывают, какие вычисления должны быть выполнены, а не как их выполнять. Традиционно мы работали с внешней итерацией, при которой четко указывали всю последовательность операций, а также как они делаются.

Такая мотивация “что, а не как” в случае лямбда-выражений является основной. Но, чтобы понять замыкания, нужно подробнее рассмотреть мотивацию функционального программирования как такового.

Лямбда-вырражения/замыкания призваны упростить функциональное программирование. Java 8 – конечно, не функциональный язык, но в нем (как и в Python) теперь обеспечивается некоторая поддержка функционального программирования, эти возможности надстроены над базисной объектно-ориентированной парадигмой.
Основная идея функционального программирования заключается в том, что можно создавать функции и манипулировать ими, в частности, создавать функции во время исполнения. Соответственно, ваша программа может оперировать не только данными, но и функциями. Представьте, какие возможности открываются перед программистом.

В чисто функциональном языке программирования есть и другие ограничения, в частности — инвариантность данных. То есть, у вас нет переменных, только неизменяемые значения. На первый взгляд это ограничение кажется чрезмерным (как вообще работать без переменных?), но оказывается, что, в сущности, при помощи значений достижимо все то же самое, что и с переменными (хотите убедиться – попробуйте Scala, этот язык не является чисто функциональным, но предусматривает возможность везде пользоваться значениями). Инвариантные функции принимают аргументы и выдают результат, не изменяя окружения; поэтому ими значительно проще пользоваться при параллельном программировании, ведь инвариантная функция не блокирует разделяемые ресурсы.
До выхода Java 8 можно было создавать функции во время выполнения только одним способом: генерировать и загружать байт-код (это довольно запутанная и сложная работа).

Для лямбда-выражений характерны две следующие черты:

Замыкания касаются именно второй возможности

Что такое замыкание?

Лямбда-выражения в Java 8

Рассмотрим тот же пример на Java с использованием лямбда-выражений:

Неоднозначная штука: мы действительно можем обратиться к n, но как только попытаемся изменить n, начнутся проблемы. Сообщение об ошибке таково: local variables referenced from a lambda expression must be final or effectively final (локальные переменные, на которые ставится ссылка из лямбда-выражения, должны быть финальными или фактически финальными).

Оказывается, что лямбда-выражения в Java замыкаются только вокруг значений, но не вокруг переменных. Java требует, чтобы эти значения были неизменны, как если бы мы объявили их final. Итак, они должны быть final независимо от того, объявляли вы их таким образом или нет. То есть, «фактически финальными». Поэтому в Java есть «замыкания с ограничениями», а не «полноценные» замыкания, которые, тем не менее, довольно полезны.

Если мы создаем объекты, расположенные не в куче, то можем изменять такие объекты, поскольку компилятор следит лишь за тем, чтобы не изменялась сама ссылка. Например:

Лямбда-выражения – как минимум, отчасти – позволяют достичь желаемой цели: теперь можно создавать функции динамически. Если вы выйдете за границы, то получите сообщение об ошибке, но обычно подобные проблемы решаемы. Выход будет не таким прямолинейным, как на Python, но ведь это все-таки Java. А конечный результат, не лишенный некоторых ограничений (давайте признаем, любой результат в Java не лишен некоторых ограничений) не так уж и плох.

Я поинтересовался, почему же эти структуры назвали «лямбдами», а не просто «замыканиями» — ведь по всем признакам это чистые замыкания. Мне ответили, что «замыкание» — неудачный и перегруженный термин. Когда кто-то говорит «настоящее замыкание», то зачастую имеет в виду такие «замыкания», которые попались ему в первом освоенном языке программирования, где имелись сущности, именуемые «замыканиями».

Я не усматриваю здесь спора «ООП против ФП», впрочем, и не собирался его устраивать. Более того, я даже «против» здесь не вижу. ООП хорошо подходит для абстрагирования данных (и пусть даже Java вынуждает вас работать с объектами, это еще не означает, что любая задача решаема при помощи объектов), а ФП — для абстрагирования поведений. Обе парадигмы полезны, и, на мой взгляд, тем более полезны, если их смешивать — и в Python, и в Java 8. Недавно мне довелось поработать с Pandoc — конвертером, написанном на чисто функциональном языке Haskell, причем у меня остались от этого самые положительные впечатления. Итак, чисто функциональные языки, также заслуживают места под солнцем.

Источник

Замыкания

Замыкание — это комбинация функции и лексического окружения, в котором эта функция была определена. Другими словами, замыкание даёт вам доступ к Scope (en-US) внешней функции из внутренней функции. В JavaScript замыкания создаются каждый раз при создании функции, во время её создания.

Лексическая область видимости

Рассмотрим следующий пример:

Выполните этот код и обратите внимание, что команда alert() внутри displayName() благополучно выводит на экран содержимое переменной name объявленной в родительской функции. Это пример так называемой лексической области видимости (lexical scoping): в JavaScript область действия переменной определяется по её расположению в коде (это очевидно лексически), и вложенные функции имеют доступ к переменным, объявленным вовне. Этот механизм и называется Lexical scoping (область действия, ограниченная лексически).

Замыкание

Рассмотрим следующий пример:

Если выполнить этот код, то результат будет такой же, как и выполнение init() из предыдущего примера: строка «Mozilla» будет показана в JavaScript alert диалоге. Что отличает этот код и представляет для нас интерес, так это то, что внутренняя функция displayName() была возвращена из внешней до того, как была выполнена.

На первый взгляд, кажется неочевидным, что этот код правильный, но он работает. В некоторых языках программирования локальные переменные-функции существуют только во время выполнения этой функции. После завершения выполнения makeFunc() можно ожидать, что переменная name больше не будет доступна. Однако, поскольку код продолжает нормально работать, очевидно, что это не так в случае JavaScript.

А вот немного более интересный пример — функция makeAdder :

По существу makeAdder — это фабрика функций: она создаёт функции, которые могут прибавлять определённое значение к своему аргументу. В примере выше мы используем нашу фабричную функцию для создания двух новых функций — одна прибавляет 5 к своему аргументу, вторая прибавляет 10.

add5 и add10 — это примеры замыканий. Эти функции делят одно определение тела функции, но при этом они сохраняют различные окружения. В окружении функции add5 x — это 5, в то время как в окружении add10 x — это 10.

Замыкания на практике

Замыкания полезны тем, что позволяют связать данные (лексическое окружение) с функцией, которая работает с этими данными. Очевидна параллель с объектно-ориентированным программированием, где объекты позволяют нам связать некоторые данные (свойства объекта) с одним или несколькими методами.

Следовательно, замыкания можно использовать везде, где вы обычно использовали объект с одним единственным методом.

Давайте рассмотрим практический пример: допустим, мы хотим добавить на страницу несколько кнопок, которые будут менять размер текста. Как вариант, мы можем указать свойство font-size на элементе body в пикселах, а затем устанавливать размер прочих элементов страницы (таких, как заголовки) с использованием относительных единиц em:

Тогда наши кнопки будут менять свойство font-size элемента body, а остальные элементы страницы просто получат это новое значение и отмасштабируют размер текста благодаря использованию относительных единиц.

Используем следующий JavaScript:

Эмуляция частных (private) методов с помощью замыканий

JavaScript не имеет встроенной возможности сделать такое, но это можно эмулировать с помощью замыкания. Частные методы полезны не только тем, что ограничивают доступ к коду, это также мощное средство глобальной организации пространства имён, позволяющее не засорять публичный интерфейс вашего кода внутренними методами классов.

Код ниже иллюстрирует, как можно использовать замыкания для определения публичных функций, которые имеют доступ к закрытым от пользователя (private) функциям и переменным. Такая манера программирования называется модульное программирование:

Заметьте, что счётчики работают независимо друг от друга. Это происходит потому, что у каждого из них в момент создания функцией makeCounter() также создавался свой отдельный контекст исполнения (окружение). То есть приватная переменная privateCounter в каждом из счётчиков это действительно отдельная, самостоятельная переменная.

Используя замыкания подобным образом, вы получаете ряд преимуществ, обычно ассоциируемых с объектно-ориентированным программированием, таких как изоляция и инкапсуляция.

Создание замыканий в цикле: Очень частая ошибка

Массив helpText описывает три подсказки для трёх полей ввода. Цикл пробегает эти описания по очереди и для каждого из полей ввода определяет, что при возникновении события onfocus для этого элемента должна вызываться функция, показывающая соответствующую подсказку.

Если вы запустите этот код, то увидите, что он работает не так, как мы ожидаем интуитивно. Какое поле вы бы ни выбрали, в качестве подсказки всегда будет высвечиваться сообщение о возрасте.

В качестве решения в этом случае можно предложить использование функции, фабричной функции (function factory), как уже было описано выше в примерах:

Соображения по производительности

Не нужно без необходимости создавать функции внутри функций в тех случаях, когда замыкания не нужны. Использование этой техники увеличивает требования к производительности как в части скорости, так и в части потребления памяти.

Как пример, при написании нового класса есть смысл помещать все методы в прототип его объекта, а не описывать их в тексте конструктора. Если сделать по-другому, то при каждом создании объекта для него будет создан свой экземпляр каждого из методов, вместо того, чтобы наследовать их из прототипа.

Давайте рассмотрим не очень практичный, но показательный пример:

Поскольку вышеприведённый код никак не использует преимущества замыканий, его можно переписать следующим образом:

Методы вынесены в прототип. Тем не менее, переопределять прототип — само по себе является плохой привычкой, поэтому давайте перепишем всё так, чтобы новые методы просто добавились к уже существующему прототипу.

Код выше можно сделать аккуратнее:

В обоих примерах выше методы определяются один раз — в прототипе. И все объекты, использующие данный прототип, будут использовать это определение без дополнительного расхода вычислительных ресурсов. Смотрите подробное описание в статье Подробнее об объектной модели.

Источник

Замыкания в JavaScript для начинающих

Замыкания — это одна из фундаментальных концепций JavaScript, вызывающая сложности у многих новичков, знать и понимать которую должен каждый JS-программист. Хорошо разобравшись с замыканиями, вы сможете писать более качественный, эффективный и чистый код. А это, в свою очередь, будет способствовать вашему профессиональному росту.

Материал, перевод которого мы публикуем сегодня, посвящён рассказу о внутренних механизмах замыканий и о том, как они работают в JavaScript-программах.

что такое замыкание java. Смотреть фото что такое замыкание java. Смотреть картинку что такое замыкание java. Картинка про что такое замыкание java. Фото что такое замыкание java

Что такое замыкание?

Замыкание — это функция, у которой есть доступ к области видимости, сформированной внешней по отношению к ней функции даже после того, как эта внешняя функция завершила работу. Это значит, что в замыкании могут храниться переменные, объявленные во внешней функции и переданные ей аргументы. Прежде чем мы перейдём, собственно, к замыканиям, разберёмся с понятием «лексическое окружение».

Что такое лексическое окружение?

Понятие «лексическое окружение» или «статическое окружение» в JavaScript относится к возможности доступа к переменным, функциям и объектам на основе их физического расположения в исходном коде. Рассмотрим пример:

Здесь у функции inner() есть доступ к переменным, объявленным в её собственной области видимости, в области видимости функции outer() и в глобальной области видимости. Функция outer() имеет доступ к переменным, объявленным в её собственной области видимости и в глобальной области видимости.

Цепочка областей видимости вышеприведённого кода будет выглядеть так:

Практические примеры замыканий

Рассмотрим, прежде чем разбирать тонкости внутреннего устройства замыканий, несколько практических примеров.

▍Пример №1

▍Пример №2

Как работают замыкания?

До сих пор мы говорили о том, что такое замыкания, и рассматривали практические примеры. Теперь поговорим о внутренних механизмах JavaScript, обеспечивающих их работу.

Для того чтобы понять замыкания, нам нужно разобраться с двумя важнейшими концепциями JavaScript. Это — контекст выполнения (Execution Context) и лексическое окружение (Lexical Environment).

▍Контекст выполнения

Контекст выполнения — это абстрактное окружение, в котором вычисляется и выполняется JavaScript-код. Когда выполняется глобальный код, это происходит внутри глобального контекста выполнения. Код функции выполняется внутри контекста выполнения функции.

В некий момент времени может выполняться код лишь в одном контексте выполнения (JavaScript — однопоточный язык программирования). Управление этими процессами ведётся с использованием так называемого стека вызовов (Call Stack).

Стек вызовов — это структура данных, устроенная по принципу LIFO (Last In, First Out — последним вошёл, первым вышел). Новые элементы можно помещать только в верхнюю часть стека, и только из неё же элементы можно изымать.

Текущий контекст выполнения всегда будет в верхней части стека, и когда текущая функция завершает работу, её контекст выполнения извлекается из стека и управление передаётся контексту выполнения, который был расположен ниже контекста этой функции в стеке вызовов.

Рассмотрим следующий пример для того, чтобы лучше разобраться в том, что такое контекст выполнения и стек вызовов:

что такое замыкание java. Смотреть фото что такое замыкание java. Смотреть картинку что такое замыкание java. Картинка про что такое замыкание java. Фото что такое замыкание java

Пример контекста выполнения

Стек вызовов этого кода выглядит так:

что такое замыкание java. Смотреть фото что такое замыкание java. Смотреть картинку что такое замыкание java. Картинка про что такое замыкание java. Фото что такое замыкание java

▍Лексическое окружение

Каждый раз, когда JS-движок создаёт контекст выполнения для выполнения функции или глобального кода, он создаёт и новое лексическое окружение для хранения переменных, объявляемых в этой функции в процессе её выполнения.

Лексическое окружение — это структура данных, которая хранит сведения о соответствии идентификаторов и переменных. Здесь «идентификатор» — это имя переменной или функции, а «переменная» — это ссылка на объект (сюда входят и функции) или значение примитивного типа.

Лексическое окружение содержит два компонента:

Взглянем на следующий фрагмент кода:

Когда JS-движок создаёт глобальный контекст выполнения для выполнения глобального кода, он создаёт и новое лексическое окружение для хранения переменных и функций, объявленных в глобальной области видимости. В результате лексическое окружение глобальной области видимости будет выглядеть так:

Обратите внимание на то, что когда функция завершит работу, её контекст выполнения извлекается из стека вызовов, но её лексическое окружение может быть удалено из памяти, а может и остаться там. Это зависит от того, существуют ли в других лексических окружениях ссылки на данное лексическое окружение в виде ссылок на внешнее лексическое окружение.

Подробный разбор примеров работы с замыканиями

Теперь, когда мы вооружились знаниями о контексте выполнения и о лексическом окружении, вернёмся к замыканиям и более глубоко проанализируем те же фрагменты кода, которые мы уже рассматривали.

▍Пример №1

Взгляните на данный фрагмент кода:

Её лексическое окружение будет выглядеть так:

Когда вызывается функция peter() (соответствующая переменная хранит ссылку на функцию displayName() ), JS-движок создаёт для этой функции новый контекст выполнения и новое лексическое окружение. Это лексическое окружение будет выглядеть так:

В функции displayName() нет переменных, поэтому её запись окружения будет пустой. В процессе выполнения этой функции JS-движок попытается найти переменную name в лексическом окружении функции.

▍Пример №2

Лексическое окружение функции getCounter() будет выглядеть так:

При выполнении этой функции система будет искать переменную counter в её лексическом окружении. В данном случае, опять же, запись окружения функции пуста, поэтому поиск переменной продолжается во внешнем лексическом окружении функции.

В результате лексическое окружение функции getCounter() после первого вызова функции count() будет выглядеть так:

Итоги

В этом материале мы поговорили о том, что такое замыкания, и разобрали глубинные механизмы JavaScript, лежащие в их основе. Замыкания — одна из важнейших фундаментальных концепций JavaScript, её должен понимать каждый JS-разработчик. Понимание замыканий — это одна из ступеней пути к написанию эффективных и качественных приложений.

Уважаемые читатели! Если вы обладаете опытом JS-разработки — просим поделиться с начинающими практическими примерами применения замыканий.

Источник

Bits of Mind

Заметки о программировании, и не только…

что такое замыкание java. Смотреть фото что такое замыкание java. Смотреть картинку что такое замыкание java. Картинка про что такое замыкание java. Фото что такое замыкание java

Замыкания в Java: что может быть

Как определить — нужна та или иная «фишка» в языке программирования или нет? Можно ли то же самое сделать стандартными средствами, или она настолько необходима, что нужно расширить сам язык новыми конструкциями, тем самим и усложнив его, и упростив?

Появление «настоящих» замыканий в Java может спровоцировать волну новых споров о «чистоте» вроде споров об универсальных типах. Однако здесь снова всё неоднозначно, поскольку замыкания — идея очень простая, однако вместе с тем достаточно мощная.

В этой статье я кратко расскажу о замыканиях для Java, которые, возможно, появятся уже в JDK 7. Скачать текущий прототип для экспериментов вот тут.

Многие вещи, описанные в документации, ещё не реализованы. По крайней мере, в текущей версии замыканий 0.5. Поэтому я опишу лишь то, что мне удалось получить при экспериментах у себя в коде, а с остальными возможностями вы можете ознакомиться, путешествую по ссылкам в конце статьи.

Так что же такое замыкание? Говоря неформально, это «вложенная» функция, которая содержит ссылки на свободные переменные (локальные переменные внешней функции). Замыкание создаётся каждый раз при выполнении её «внешней» функции. Мы можем выполнять нашу функцию, передавать в другие функции, а так же возвращать из других функций.

Анонимные классы как замыкания

В некотором своём виде замыкания, или лямбда-функции, в Java уже косвенно поддерживаются через внутренние анонимные классы. Это вполне объектно-ориентированное решение.

Вот как выглядит пример нечто похожего на замыкание с использованием анонимных классов:

Замыкаем map и each с помощью анонимных классов

Возможно, вы помните пример с массивом из первой моей статьи. Мы напишем метод map, возвращающий новый массив, состоящий из элементов входного массива, к которым применена некая функция. Всё дело в том, что мы хотим указать эту функцию прямо в месте вызова map. Для этого нам нужно определить интерфейс, а позже реализовать его в нашем анонимном типе.

Достаточно много кода ради такой простой задачи. Помимо этого с анонимными типами мы имеем ещё несколько проблем. Например, мы не можем внутри нашего внутреннего класса изменять внешние переменные. Если мы хотим с ними работать, то мы должны объявить их как final. Так, если у нас есть метод each:

Мы не можем сделать так:

А если мы, например, захотим кинуть исключение из тела нашего «замыкания», то и тут нас подстерегают сложности и много излишнего кода. Компилятор может сгенерировать его автоматически, предоставив нам возможность записывать то, чего мы хотим добиться, другим, более элегантным способом. Плюс ко всему здесь значению ключевых слов this, break, continue и return придаётся не совсем не тот смысл, который мы можем ожидать от замыкания.

Замыкания как замыкания

Введение в язык «настоящих» замыканий призвано сократить количество кода, необходимого для выражения этой идеи. У нас появились новые «функциональные типы». Вот пример:

Если нам необходимо будет кидать исключение из замыкания, то объявить это мы можем следующим образом:

В конечном счёте, для этого генерируются интерфейсы, подобно тому, что мы рассмотрели в предыдущей главе.

Так как замыкания теперь у нас настоящие, мы можем изменять «внешние» переменные.

Даст следующий вывод:

Замыкаем map и each по-настоящему

Пользуясь новыми возможностями, перепишем нашу функцию map:

Нечто похожее на интерфейс OneArgFunc, который мы определяли раньше сами, будет сгенерирован автоматически. Использовать функцию мы можем так:

Теперь на счёт функции each. Используя следующую версию:

Мы можем проделать то, что в прошлый раз не получилось:

Ещё пример

Допустим, нам нужно выполнить что-то в отдельном потоке. Мы можем поступить так:

А можем и по-другому, с использованием замыканий. Представим, что у нас есть некая функция:

Так что теперь мы можем писать более лаконично:

Либо вообще так (но у меня следующий вариант не скомпилировался):

Заключение

Думаю, введение замыканий в Java может быть хорошей идеей. Они могут помочь не только в работе с контейнерами и алгоритмами, но и других случаях. Однако мне, разбалованному фишками C# 3.0, кажется, что здесь не хватает ещё вывода типов, методов расширения и прочего «сахара». В документации по замыканиям рассказано о «Control invocation syntax», позволяющему ещё больше упростить синтаксис замыканий (например, не писать круглые скобки или => там где без этого можно обойтись), однако запустить эти примеры у меня не получилось. Видимо, всё это ещё в разработке. Тем не менее, радует, что разработка ведётся, и интересно будет проследить за тем, куда она заведёт :).

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *