Perché abbiamo bisogno di "funzioni di callback"?

16

Sto leggendo il libro programming in Lua . Diceva che

Closures provide a valuable tool in many contexts. As we have seen, they are useful as arguments to higher-order functions such as sort. Closures are valuable for functions that build other functions too, like our newCounter example; this mechanism allows Lua programs to incorporate sophisticated programming techniques from the functional world. Closures are useful for callback functions, too. A typical example here occurs when you create buttons in a conventional GUI toolkit. Each button has a callback function to be called when the user presses the button; you want different buttons to do slightly different things when pressed. For instance, a digital calculator needs ten similar buttons, one for each digit. Y ou can create each of them with a function like this:

function digitButton (digit)
  return Button{label = tostring(digit),
                action = function ()
                  add_to_display(digit)
                  end}
end

Sembra che se chiamo digitButton , restituirà action (questo creerà una chiusura), quindi, posso accedere a digit passato a digitButton .

La mia domanda è questa:

Why we need call back functions? what situations can I apply this to?

L'autore ha detto:

In this example, we assume that Button is a toolkit function that creates new buttons; label is the button label; and action is the callback closure to be called when the button is pressed. The callback can be called a long time after digitButton did its task and after the local variable digit went out of scope, but it can still access this variable.

secondo l'autore, penso che un esempio simile sia come questo:

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()

quindi the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.

    
posta Lucas Li 23.04.2013 - 13:34
fonte

10 risposte

45

Da Guy 1 a Guy 2: hey dude Voglio fare qualcosa quando un utente clicca lì, richiamami quando succede, va bene?

Guy 2 richiama Guy 1 quando un utente fa clic qui.

    
risposta data 23.04.2013 - 16:55
fonte
21

No, non restituirà mai return l'azione. Il pulsante lo esegue quando l'utente fa clic su di esso. E questa è la risposta. Hai bisogno di funzioni di callback quando vuoi definire le azioni che dovrebbero accadere in un altro componente in reazione ad un evento che non controlli (il ciclo degli eventi, che fa parte del sistema, eseguirà un metodo del pulsante che a sua volta eseguirà l'azione).

    
risposta data 23.04.2013 - 13:45
fonte
16

Penso che un esempio migliore per l'uso dei callback sia nelle funzioni asincrone. Non posso parlare per Lua, ma in JavaScript, una delle azioni asincrone più comuni è contattare un server tramite AJAX.

La chiamata AJAX è asincrona, ovvero se fai qualcosa di simile:

var ajax = ajaxCall();
if(ajax == true) {
  // Do something
}

il contenuto del blocco if non viene eseguito correttamente e, quando lo fa, è solo perché la funzione ajaxCall() è terminata prima che l'esecuzione abbia raggiunto l'istruzione if .

Tuttavia, i callback eliminano questo problema, assicurandosi che la chiamata asincrona sia terminata prima di chiamare la funzione richiesta. Quindi, il tuo codice cambierebbe in qualcosa del genere:

function ajaxCallback(response) {   
  if(response == true) {
    // Do something   
  }
}

ajaxCall(ajaxCallback);

Lo scopo di questo è di consentire di fare cose come raccogliere dati, senza interferire con altre cose, come disegnare l'interfaccia. Se la raccolta dei dati era sincrona, l'interfaccia non rispondeva all'applicazione in attesa di ottenere i dati. Un'interfaccia che non risponde è molto negativa per l'esperienza dell'utente, perché molti utenti penseranno che l'applicazione si sia "bloccata" e proverà a terminare il processo.

Per vedere questo in azione, devi solo guardare qualsiasi sito web che fa qualsiasi tipo di aggiornamento senza ricaricare l'intera pagina. Twitter, LinkedIn e i siti StackExchange sono buoni esempi. Lo "scorrimento continuo" di Twitter dei feed e le notifiche di SE (sia per le notifiche degli utenti che per le notifiche che una domanda ha una nuova attività) sono alimentate da chiamate asincrone. Quando vedi uno spinner da qualche parte, significa che la sezione ha effettuato una chiamata asincrona e sta aspettando che la chiamata finisca, ma puoi interagire con altre cose sull'interfaccia (e persino fare altre chiamate asincrone). Una volta terminata la chiamata, reagirà e aggiornerà l'interfaccia di conseguenza.

    
risposta data 23.04.2013 - 15:43
fonte
12

Hai posto la domanda

Why we need "call back functions"?

Cercherò di rispondere in maniera concisa e chiara (se non riesco a farlo, fai riferimento al link wiki in fondo a questa risposta).

I callback vengono utilizzati per rinviare l'implementazione specifica di qualcosa all'ultimo momento possibile.

L'esempio del pulsante ne è una buona dimostrazione. Supponiamo che tu voglia avere un pulsante nella tua applicazione che stampa una pagina sulla stampante, potremmo immaginare un mondo in cui dovresti codificare un'intera nuova% classe% co_de per farlo.

Fortunatamente, abbiamo la nozione di callback (l'ereditarietà e l'uso del modello di modello è anche una specie di callback semantica) quindi non abbiamo bisogno di farlo.

Invece di ri-implementare ogni aspetto di un pulsante, ciò che facciamo è aggiungere all'implementazione del pulsante. Il PrinterButton ha il concetto di fare qualcosa quando viene premuto. Diciamo semplicemente che cos'è quel qualcosa.

Questo meccanismo di iniezione del comportamento nei framework è chiamato callback.

Esempio:

Inseriamo alcuni comportamenti in un pulsante HTML:

<button onclick="print()">Print page through a callback to the print() method</button>

In questa istanza, Button punta a un callback, che per questo esempio è il metodo onclick .

link

    
risposta data 23.04.2013 - 15:36
fonte
8

Why we need call back functions? what situations can I apply this to?

Le funzioni di callback sono molto utili nella programmazione basata sugli eventi. Ti consentono di configurare il tuo programma in modo tale che gli eventi attivino il codice corretto. Questo è molto comune nei programmi con GUI in cui gli utenti possono fare clic su qualsiasi elemento dell'interfaccia utente (come pulsanti o voci di menu) e verrà eseguito il codice appropriato.

    
risposta data 23.04.2013 - 16:30
fonte
2

Cosa succede senza callback:

Guy 1: Okay, sto aspettando che succeda quella cosa. (fischietti, twiddles thumbs)

Guy 2: Dannazione! Perché Guy 1 non mi mostra roba? Voglio vedere che succede qualcosa !! Dov'è la mia roba? Come si dovrebbe fare qualcosa qui intorno?

    
risposta data 23.04.2013 - 22:33
fonte
1

Firstoff, il termine callback si riferisce a una chiusura che viene utilizzata per qualcosa.

Ad esempio, supponiamo di creare una funzione di chiusura e di memorizzarla in una variabile. Non è una richiamata, perché non viene utilizzata per nulla.

Supponiamo però di creare una chiusura e di memorizzarla da qualche parte che verrà chiamata quando succede qualcosa. Ora viene definito un callback.

Di solito, i callback sono creati da diverse parti del programma rispetto alle parti che li chiamano. Quindi è facile immaginare che alcune parti del programma stiano "richiamando" le altre parti.

In parole povere, i callback consentono a una parte del programma di dire a un'altra parte di fare qualcosa (qualsiasi cosa) quando succede qualcosa.

Come per le variabili mantenute in vita a causa dell'uso in una chiusura, si tratta di una funzionalità completamente diversa chiamata upvalues (a.k.a. "estensione della durata delle variabili locali" tra coloro che non parlano Lua). Ed è anche molto utile.

    
risposta data 24.04.2013 - 08:56
fonte
1

I callback sono in circolazione fin dai primi giorni di Fortran, almeno. Ad esempio, se si dispone di un risolutore ODE (equazione differenziale ordinaria), come un solutore di Runge-Kutta, potrebbe apparire come segue:

subroutine rungekutta(neq, t, tend, y, deriv)
  integer neq             ! number of differential equations
  double precision t      ! initial time
  double precision tend   ! final time
  double precision y(neq) ! state vector
  ! deriv is the callback function to evaluate the state derivative
  ...
  deriv(neq, t, y, yprime) ! call deriv to get the state derivative
  ...
  deriv(neq, t, y, yprime) ! call it several times
  ...
end subroutine

Consente al chiamante di personalizzare il comportamento della subroutine trasmettendogli una funzione per scopi speciali da chiamare quando necessario. Ciò consente di utilizzare il solutore ODE per simulare un'ampia varietà di sistemi.

    
risposta data 25.04.2013 - 14:59
fonte
1

Ci siamo imbattuti in questo e volevamo fornire una risposta più aggiornata ...

Le funzioni di callback ci permettono di fare qualcosa con i dati in un momento più tardi , consentendo di eseguire il resto del nostro codice, anziché attendere. Il codice asincrono ci consente questo lusso di eseguire qualsiasi cosa più tardi . L'esempio più leggibile di funzioni di callback che ho trovato sono Promises in JavaScript. Nell'esempio seguente ogni volta che vedi la funzione (risultato) o (newResult) o (finalResult) ... queste sono funzioni di callback. Il codice tra parentesi graffe viene eseguito una volta che i dati tornano dal server. Solo a questo punto avrebbe senso eseguire queste funzioni poiché ora sono disponibili i dati di cui hanno bisogno.

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

il codice è preso da ... link

Speriamo che questo aiuti qualcuno. Questo è ciò che ha aiutato ME a comprendere i callback:)

    
risposta data 27.03.2018 - 08:54
fonte
-2

Non conosco lua, ma in generale metodi di callback alcuni come il multithreading. Ad esempio, nella programmazione dello sviluppo di applicazioni mobili, la maggior parte delle applicazioni funziona come inviare una richiesta al server e giocare con l'interfaccia utente con i dati come risposta dal server. Quando l'utente invia una richiesta al server, ci vorrà del tempo per ottenere una risposta dal server, ma per la migliore UI UX non dovrebbe rimanere bloccata.

Per questo motivo usiamo thread multipli per fare operazioni parallele. Quando riceviamo la risposta dal server, dobbiamo aggiornare l'interfaccia utente. dobbiamo notificare da quel thread per aggiornare. dal mondo funzionale. Questo tipo di chiamate di funzione sono chiamate metodi di callback. Quando chiami questi metodi, il controllo dovrebbe tornare al thread principale. Ad esempio i metodi di callback sono blocchi in oggettivo-C.

    
risposta data 23.04.2013 - 20:45
fonte

Leggi altre domande sui tag