Подтвердить что ты не робот

Когда использовать закрытие

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

  • Обработчики кликов кнопки Swing
  • Все, что связано с Runnable или Callable (т.е. отправляет задачу ThreadPoolExecutor)
  • Анализ XML на основе событий SAX
  • Код доступа к базе данных JDBC, переданный через общий исполнитель транзакций, для сокращения приема/освобождения соединения шаблонов

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

Ответ 4

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

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, reduceLeft и других методов в коллекциях. Большинство разработчиков Java считают это интересным.

Ответ 5

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

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

Кроме того, Goslings upvote of them в начале дискуссий по закрытию Java будет интересен разработчикам Java. Обратите внимание, что он также ссылается на оригинальное предложение Neal Gafter для их включения в Java.