Я читаю книгу programming in Lua
. Он сказал, что
Закрытия предоставляют ценный инструмент во многих контекстах. Как мы уже видели, они полезны в качестве аргументов для функций высшего порядка, таких как sort. Замыкания полезны для функций, которые также создают другие функции, как, например, наш пример newCounter; Этот механизм позволяет программам Lua включать сложные методы программирования из функционального мира. Замыкания также полезны для функций обратного вызова. Типичный пример здесь происходит, когда вы создаете кнопки в обычном инструментарии GUI. Каждая кнопка имеет функцию обратного вызова, которая вызывается, когда пользователь нажимает кнопку; Вы хотите, чтобы разные кнопки делали немного разные вещи при нажатии. Например, цифровому калькулятору нужно десять одинаковых кнопок, по одной для каждой цифры. Вы можете создать каждый из них с помощью такой функции:
function digitButton (digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
Кажется, что если я вызову digitButton
, он вернет action
(это создаст замыкание), поэтому я могу получить доступ к digit
переданному digitButton
.
Мой вопрос таков:
Why we need call back functions? what situations can I apply this to?
Автор сказал:
В этом примере мы предполагаем, что Button является функцией инструментария, которая создает новые кнопки; метка - это метка кнопки; и action - это закрытие обратного вызова, которое вызывается при нажатии кнопки. Обратный вызов может быть вызван долгое время после того, как digitButton выполнил свою задачу и после того, как цифра локальной переменной вышла из области видимости, но он все еще может получить доступ к этой переменной.
по мнению автора, я думаю, что похожий пример выглядит так:
function Button(t)
-- maybe you should set the button here
return t.action -- so that you can call this later
end
function add_to_display(digit)
print ("Display the button label: " .. tostring(digit))
end
function digitButton(digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
click_action = digitButton(10)
click_action()
Таким образом, the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.
Ответы:
Парень 1 - Парень 2: эй, чувак, я хочу сделать что-нибудь, когда пользователь нажмет там, перезвонить мне, когда это произойдет, хорошо?
Парень 2 перезванивает Парню 1, когда пользователь нажимает здесь.
источник
Нет, это никогда не вернет действие. Кнопка выполнит ее, когда пользователь нажмет на нее. И это ответ. Вам нужны функции обратного вызова, когда вы хотите определить действия, которые должны произойти в другом компоненте в ответ на событие, которым вы не управляете (цикл обработки событий, который является частью системы, выполнит метод кнопки, которая, в свою очередь, выполнит Действие).
источник
Я думаю, что лучший пример использования обратных вызовов - это асинхронные функции. Я не могу говорить за Lua, но в JavaScript одним из наиболее распространенных асинхронных действий является соединение с сервером через AJAX.
Вызов AJAX является асинхронным, то есть если вы делаете что-то вроде этого:
содержимое
if
блока не будет надежно работать правильно, и когда это происходит, то только потому, чтоajaxCall()
функция завершилась до того, как выполнение достиглоif
оператора.Однако обратные вызовы устраняют эту проблему, обеспечивая завершение асинхронного вызова перед вызовом требуемой функции. Итак, ваш код изменится на что-то вроде этого:
Цель этого состоит в том, чтобы позволить вам делать такие вещи, как сбор данных, не мешая другим вещам, таким как рисование интерфейса. Если сбор данных был синхронным, то интерфейс перестал бы отвечать на запросы, поскольку приложение ожидало получения данных. Не отвечающий интерфейс очень плох для пользовательского опыта, потому что большинство пользователей подумают, что приложение "упало" и попытаются завершить процесс.
Чтобы увидеть это в действии, вам просто нужно взглянуть на любой веб-сайт, который выполняет какие-либо обновления без перезагрузки всей страницы. Twitter, LinkedIn и сайты StackExchange являются хорошими примерами. «Бесконечная прокрутка» каналов в Твиттере и уведомления SE (как для пользовательских уведомлений, так и для уведомлений о том, что вопрос имеет новую активность) приводятся в действие асинхронными вызовами. Когда вы где-то видите спиннер, это означает, что секция выполнила асинхронный вызов и ожидает его завершения, но вы можете взаимодействовать с другими объектами интерфейса (и даже делать другие асинхронные вызовы). Как только этот вызов завершится, он отреагирует и обновит интерфейс соответствующим образом.
источник
Вы задали вопрос
Я постараюсь ответить на него кратко и ясно (если мне это не удастся, пожалуйста, обратитесь к ссылке вики внизу этого ответа).
Обратные вызовы используются, чтобы отложить конкретную реализацию чего-либо до последнего возможного момента.
Пример кнопки является хорошей иллюстрацией этого. Скажем, вы хотите, чтобы в вашем приложении была кнопка, которая печатает страницу на принтере, мы могли бы представить себе мир, в котором вам придется кодировать целый новый
PrinterButton
класс, чтобы сделать это.К счастью, у нас есть понятие обратных вызовов (наследование и использование шаблона шаблона также является своего рода семантической функцией обратного вызова), поэтому нам не нужно это делать.
Вместо того, чтобы повторно реализовывать каждый аспект кнопки, мы добавляем к реализации кнопки.
Button
Имеет концепцию делать что - то , когда она нажата. Мы просто говорим, что это такое.Этот механизм внедрения поведения в рамки называется обратными вызовами.
Пример:
Давайте добавим некоторое поведение в кнопку HTML:
В этом случае
onclick
указывает на обратный вызов, который для этого примера являетсяprint()
методом.http://en.wikipedia.org/wiki/Callback_(computer_programming)
источник
Функции обратного вызова очень полезны в программировании на основе событий. Они позволяют вам настроить вашу программу таким образом, чтобы события вызывали правильный код. Это очень часто встречается в программах с графическим интерфейсом, где пользователи могут щелкнуть любой элемент пользовательского интерфейса (например, кнопки или пункты меню), и будет запущен соответствующий код.
источник
Что происходит без обратных вызовов:
Парень 1: Хорошо, я жду, когда это произойдет. (свистит, вертит пальцами)
Парень 2: Черт возьми! Почему Гай 1 не показывает мне вещи? Я хочу видеть, что происходит !! Где мои вещи? Как кто-нибудь должен делать что-то здесь?
источник
Прежде всего, термин обратный вызов относится к закрытию, которое используется для чего-то.
Например, предположим, что вы создали функцию замыкания и просто сохранили ее в переменной. Это не обратный вызов, потому что он не используется ни для чего.
Но предположим, что вы создаете замыкание и храните его где-нибудь, чтобы оно вызывалось, когда что-то происходит. Теперь это называется обратным вызовом.
Обычно обратные вызовы создаются разными частями программы, а не частями, которые их вызывают. Поэтому легко представить, что некоторые части программы «перезванивают» другим частям.
Проще говоря, обратные вызовы позволяют одной части программы сообщать другой части что-то делать (что-либо), когда что-то происходит.
Что касается переменных, которые поддерживаются живыми из-за использования в замыкании, это совершенно другая функция, называемая upvalues (то есть «продление времени жизни локальных переменных» среди тех, кто не говорит на Lua). И это тоже весьма полезно.
источник
Extending the lifetime of local variables
это тоже сказать терминupvalue
.Обратные вызовы были вокруг с первых дней Фортрана, по крайней мере. Например, если у вас есть решатель ODE (обыкновенного дифференциального уравнения), такой как решатель Рунге-Кутты, он может выглядеть так:
Это позволяет вызывающей программе настраивать поведение подпрограммы, передавая ей специальную функцию, которая вызывается при необходимости. Это позволяет использовать решатель ODE для моделирования широкого спектра систем.
источник
Наткнулся на это и хотел предоставить более актуальный ответ ...
Функции обратного вызова позволяют нам что-то делать с данными позднее , позволяя выполнять остальную часть нашего кода вместо того, чтобы ждать его. Асинхронный код позволяет нам эту роскошь выполнить что-нибудь позже . Наиболее читаемый пример функций обратного вызова, с которыми я сталкивался, - это обещания в JavaScript. В приведенном ниже примере каждый раз, когда вы видите функцию (результат) или (newResult) или (finalResult) ... это функции обратного вызова. Код в их фигурных скобках выполняется, как только данные возвращаются с сервера. Только на этом этапе имеет смысл выполнять эти функции, поскольку теперь необходимые данные доступны.
код взят из ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Надеюсь, это кому-нибудь поможет. Это то, что помогло мне понять обратные вызовы :)
источник
Я не знаю lua, но в общем случае методы обратного вызова, такие как многопоточность. Например, в программировании разработки мобильных приложений большинство приложений работают подобно отправке запроса на сервер и воспроизведению пользовательского интерфейса с данными, полученными в ответ от сервера. Когда пользователь отправляет запрос на сервер, потребуется время, чтобы получить ответ от сервера, но для лучшего UX пользовательский интерфейс не должен застрять.
Из-за этого мы используем несколько потоков для параллельных операций. Когда мы получаем ответ от сервера, нам нужно обновить интерфейс. мы должны сообщить из этой темы, чтобы обновить. из функционального мира. Этот тип вызовов функций называется методами обратного вызова. Когда вы вызываете эти методы, контроль должен возвращаться в основной поток. Например, методы обратного вызова являются блоками в target-C.
источник