Estou lendo o livro programming in Lua
. Disse que
Os fechamentos fornecem uma ferramenta valiosa em muitos contextos. Como vimos, eles são úteis como argumentos para funções de ordem superior, como ordenação. Os fechamentos são valiosos para funções que constroem outras funções também, como nosso exemplo newCounter; esse mecanismo permite que os programas Lua incorporem técnicas sofisticadas de programação do mundo funcional. Os fechamentos também são úteis para funções de retorno de chamada. Um exemplo típico aqui ocorre quando você cria botões em um kit de ferramentas da GUI convencional. Cada botão possui uma função de retorno de chamada a ser chamada quando o usuário pressiona o botão; você deseja que botões diferentes façam coisas ligeiramente diferentes quando pressionados. Por exemplo, uma calculadora digital precisa de dez botões semelhantes, um para cada dígito. Você pode criar cada um deles com uma função como esta:
function digitButton (digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
Parece que se eu chamar o digitButton
, ele retornará o action
(isso criará um fechamento), para que eu possa acessar o digit
passado para digitButton
.
Minha pergunta é:
Why we need call back functions? what situations can I apply this to?
O autor disse:
Neste exemplo, assumimos que Button é uma função do kit de ferramentas que cria novos botões; label é o rótulo do botão; e action é o fechamento do retorno de chamada a ser chamado quando o botão é pressionado. O retorno de chamada pode ser chamado muito tempo depois que o digitButton executou sua tarefa e depois que o dígito da variável local ficou fora do escopo, mas ainda pode acessar essa variável.
de acordo com o autor, acho que um exemplo semelhante é assim:
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()
portanto, the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.
Respostas:
Cara 1 a Cara 2: ei cara, eu quero fazer alguma coisa quando um usuário clicar lá, me ligar de volta quando isso acontecer bem?
O Guy 2 chama de volta o Guy 1 quando um usuário clica aqui.
fonte
Não, nunca retornará a ação. O botão irá executá- lo quando o usuário clicar nele. E essa é a resposta. Você precisa de funções de retorno de chamada quando desejar definir ações que devem ocorrer em outro componente em reação a um evento que você não controla (o loop de eventos, que faz parte do sistema, executará um método do botão que, por sua vez, executará a acção).
fonte
Eu acho que um exemplo melhor para o uso de retornos de chamada está em funções assíncronas. Não posso falar por Lua, mas em JavaScript, uma das ações assíncronas mais comuns é entrar em contato com um servidor via AJAX.
A chamada AJAX é assíncrona, ou seja, se você fizer algo assim:
o conteúdo do
if
bloco não será executado corretamente de maneira confiável e, quando o fizer, é apenas porque aajaxCall()
função terminou antes da execução chegar àif
instrução.No entanto, os retornos de chamada eliminam esse problema, garantindo que a chamada assíncrona seja concluída antes de chamar a função necessária. Portanto, seu código mudaria para algo assim:
O objetivo disso é permitir que você faça coisas como coletar dados, sem interferir em outras coisas, como desenhar a interface. Se a coleta de dados fosse síncrona, a interface deixaria de responder à medida que o aplicativo aguardasse para obter os dados. Uma interface que não responde é muito ruim para a experiência do usuário, porque a maioria dos usuários pensa que o aplicativo "travou" e tenta finalizar o processo.
Para ver isso em ação, basta olhar para qualquer site que faça qualquer tipo de atualização sem recarregar a página inteira. Twitter, LinkedIn e os sites StackExchange são bons exemplos. A "rolagem interminável" do Twitter de feeds e as notificações do SE (para notificações do usuário e notificações de que uma pergunta tem nova atividade) são alimentadas por chamadas assíncronas. Quando você vê um botão giratório em algum lugar, isso significa que a seção fez uma chamada assíncrona e aguarda o término da chamada, mas você pode interagir com outras coisas na interface (e até fazer outras chamadas assíncronas). Quando a chamada terminar, ela reagirá e atualizará a interface de acordo.
fonte
Você fez a pergunta
Tentarei respondê-lo de maneira concisa e clara (se eu falhar nisso, consulte o link do wiki na parte inferior desta resposta).
Os retornos de chamada são usados para adiar a implementação específica de algo até o último momento possível.
O exemplo do botão é uma boa ilustração disso. Digamos que você queira ter um botão em seu aplicativo que imprima uma página na impressora; poderíamos imaginar um mundo em que você teria que codificar uma nova
PrinterButton
classe inteira para fazer isso.Felizmente, temos a noção de retornos de chamada (herança e o uso do padrão de modelo também é um tipo de semântica de retorno de chamada), portanto, não precisamos fazer isso.
Em vez de reimplementar todos os aspectos de um botão, o que fazemos é adicionar à implementação do botão. O
Button
tem o conceito de fazer algo quando pressionado. Simplesmente dizemos o que é isso.Esse mecanismo de injeção de comportamento nas estruturas é chamado de retorno de chamada.
Exemplo:
Vamos injetar algum comportamento em um botão HTML:
Nesse caso,
onclick
aponta para um retorno de chamada, que para este exemplo é oprint()
métodohttp://en.wikipedia.org/wiki/Callback_(computer_programming)
fonte
As funções de retorno de chamada são muito úteis na programação orientada a eventos. Eles permitem que você configure seu programa de forma que os eventos acionem o código correto. Isso é muito comum em programas com GUIs em que os usuários podem clicar em qualquer elemento da interface do usuário (como botões ou itens de menu) e o código apropriado será executado.
fonte
O que acontece sem retornos de chamada:
Cara 1: Ok, estou esperando que isso aconteça. (assobios, polegares giratórios)
Cara 2: Caramba! Por que o Guy 1 não está me mostrando coisas? Eu quero ver coisas acontecendo !! Onde estão as minhas coisas? Como alguém pode fazer alguma coisa por aqui?
fonte
Primeiro, o termo retorno de chamada refere-se a um fechamento que está sendo usado para algo.
Por exemplo, suponha que você crie uma função de fechamento e apenas armazene-a em uma variável. Não é um retorno de chamada, porque não está sendo usado para nada.
Mas, suponha que você crie um fechamento e armazene-o em algum lugar que será chamado quando algo acontecer. Agora é chamado de retorno de chamada.
Geralmente, os retornos de chamada são criados por diferentes partes do programa que as partes que os chamam. Portanto, é fácil imaginar que algumas partes do programa estão "retornando" as outras partes.
Simplificando, os retornos de chamada permitem que uma parte do programa diga à outra parte para fazer algo (qualquer coisa) quando algo acontecer.
Quanto às variáveis mantidas vivas devido ao uso em um fechamento, esse é um recurso completamente diferente chamado upvalues (também conhecido como "estendendo a vida útil das variáveis locais" entre aqueles que não falam Lua). E é bastante útil também.
fonte
Extending the lifetime of local variables
é também para dizer o termoupvalue
.Os retornos de chamada existem desde os primeiros dias de Fortran, pelo menos. Por exemplo, se você tiver um solucionador de ODE (equação diferencial ordinária), como um solucionador de Runge-Kutta, ele poderá se parecer com o seguinte:
Ele permite que o chamador personalize o comportamento da sub-rotina, passando para ela uma função de finalidade especial a ser chamada quando necessário. Isso permite que o solucionador ODE seja usado para simular uma ampla variedade de sistemas.
fonte
Tropecei sobre isso e queria fornecer uma resposta mais atualizada ...
As funções de retorno de chamada nos permitem fazer algo com os dados posteriormente , permitindo que o restante do nosso código seja executado, em vez de esperar por eles. O código assíncrono nos permite esse luxo de executar qualquer coisa posteriormente . O exemplo mais legível das funções de retorno de chamada que encontrei são Promessas em JavaScript. No exemplo abaixo, toda vez que você vê a função (resultado) ou (newResult) ou (finalResult) ... essas são funções de retorno de chamada. O código entre colchetes é executado assim que os dados retornam do servidor. Somente nesse ponto faria sentido executar essas funções, pois agora os dados de que eles precisam estão disponíveis.
o código é retirado de ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Felizmente, isso ajuda alguém. Isto é o que me ajudou a entender retornos de chamada :)
fonte
Eu não sei lua, mas em geral métodos de retorno de chamada alguns que gostam de multithreading. Por exemplo, na programação de desenvolvimento de aplicativos móveis, a maioria dos aplicativos funciona como o envio de solicitação ao servidor e a reprodução da interface do usuário com os dados, como resposta do servidor. Quando o usuário envia uma solicitação ao servidor, leva um tempo para obter a resposta do servidor, mas a melhor interface do usuário do UX não deve ser bloqueada.
Por isso, usamos vários threads para realizar operações paralelas. Quando obtemos a resposta do servidor, precisamos atualizar a interface do usuário. temos que notificar a partir desse segmento para atualizar. do mundo funcional. Esse tipo de chamada de função é chamado de método de retorno de chamada. Quando você chama esses métodos, o controle deve retornar ao thread principal. Por exemplo, métodos de retorno de chamada são blocos no objetivo-C.
fonte