Когда использовать Closures - PullRequest
13 голосов
/ 21 июня 2011

Примечание: перейдите вниз к «Вопросу» ниже, если вы просто хотите пропустить контекст

Когда я говорю о Scala, я почти всегда уверен, что меня спросят "а когда бы вы использовали Closure?" Обычно я говорю «подождите, пока я не покажу вам для понимания», а затем я показываю, как для понимания может быть сведено к использованию flatMap / map + closures.

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

Обычно я говорю с разработчиками Java, когда говорю о Scala, и мне приходит в голову одна аналогия: «Вы знаете, когда создаете анонимный внутренний класс, которому нужен доступ к переменной где-то выше, где класс был определен? как закрытие ". Поэтому я использую обработку обратного вызова события в качестве одного конкретного примера (поскольку в этом сценарии неизбежно используются анонимные внутренние классы).

Учитывая аудиторию (нет опыта или ограниченный опыт работы с ФП), я не буду обсуждать такие термины, как монады, эти люди обычно ищут конкретные / прагматические примеры, к которым они могут относиться.

Вопрос: У кого-нибудь есть свой собственный способ успешного объяснения замыканий, который действительно ударил по домам для разработчиков Java (или другого языка OO)?

Ответы [ 5 ]

9 голосов
/ 21 июня 2011

Многие Java-разработчики уже знакомы с «closures-lite» - шаблонами проектирования, которые имитируют замыкания с помощью классов:

  • посетитель
  • команда
  • стратегия
  • functor (см. Много примеров обработки в коллекциях Google Guice)
  • callback / listener (большие полосы Swing)

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

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

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

6 голосов
/ 21 июня 2011

Почему бы вам не изменить порядок представления? Когда вы обычно представляете Closures, представляйте хорошо известный шаблон (например, Listener или Visitor). Затем покажите, как Closures решают проблему без создания дополнительных «вспомогательных» объектов или ненужного фрейма кода.

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

1 голос
/ 23 октября 2013

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

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

Кроме того, Госвинс упомянул о них в первые дни дебатов о закрытии Java будет представлять интерес для разработчиков Java. Обратите внимание, что он также ссылается на исходное предложение Нила Гафтера об их включении в Java.

1 голос
/ 21 июня 2011

Если вы имеете в виду анонимные функции в целом, а не просто замыкания, я обычно использую следующий пример.Дайте простую коллекцию (в данном случае список имен) и покажите, насколько проще запрашивать и изменять анонимные функции.

Java - получить новый список имен, начинающийся с «A»:

List<String> names = Arrays.asList("Ed", "Bob", "Anna");
List<String> namesOnA = new ArrayList<String>();

for(String name : names) {
  if(name.startsWith("A")) {
    namesOnA.add(name);
  }
}

Scala - получить список имен, начинающихся с "A":

val names = List("Ed", "Bob", "Anna")
val namesOnA = names.filter(_.startsWith("A"))

Подобные примеры с использованием map, reduLeft и других методов в коллекциях.Большинство разработчиков Java считают это интересным.

1 голос
/ 21 июня 2011

Я думаю, что вы на правильном пути в отношении замыканий анонимных внутренних классов для представления этой концепции разработчикам Java.Я рекомендую взять некоторую проблему, которая включает интенсивное использование обратных вызовов, и показать слайд с параллельным сравнением кода, требуемого в Java, с использованием анонимных внутренних классов, и кода, требуемого в Scala, с использованием замыканий.

ЗдесьВот несколько идей для решения проблем, связанных с обратными вызовами:

  1. Обработчики щелчков кнопок Swing
  2. Все, что связано с Runnable или Callable (т.е. отправка задачи в ThreadPoolExecutor)
  3. Синтаксический анализ XML на основе событий SAX
  4. Код доступа к базе данных на основе JDBC, переданный через общего исполнителя транзакций для сокращения получения / освобождения стандартного соединения

Для каждого из этих примеров я ожидаючто решение Scala / замыкание окажется короче и проще, чем решение Java / анонимного внутреннего класса.

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