Domanda

Non ho mai utilizzato funzioni annidate, ma ho visto riferimenti ad esse in diverse lingue (così come classi annidate, che presumo siano correlate).

  • Cos'è una funzione annidata?
  • Perché?!?
  • Cosa puoi fare con una funzione annidata che non puoi fare in nessun altro modo?
  • Cosa puoi fare con una funzione annidata che è difficile o inelegante senza funzioni annidate?

Presumo che le funzioni annidate siano semplicemente un artefatto nel trattare tutto come un oggetto, e se gli oggetti possono contenere altri oggetti, ne consegue.

Le funzioni annidate hanno uno scopo (in generale, suppongo che le lingue differiscano in questo) proprio come le variabili all'interno di una funzione hanno uno scopo?

Aggiungi la lingua a cui fai riferimento se non sei sicuro che la tua risposta sia indipendente dalla lingua.

-Adamo

È stato utile?

Soluzione

Un uso popolare di funzioni annidate è chiusure . In un scope lessicale lingua con funzioni di prima classe è possibile utilizzare le funzioni per memorizzare i dati. Un semplice esempio in Scheme è un contatore:

(define (make-counter)
  (let ((count 0))                ; used to store the count
    (define (counter)             ; this is the counter we're creating
      (set! count (+ count 1))    ; increment the count
      count)                      ; return the new count
    counter))                     ; return the new counter function

(define mycounter (make-counter)) ; create a counter called mycounter

(mycounter)                       ; returns 1

(mycounter)                       ; returns 2

In questo esempio, il contatore nido funzione all'interno della funzione make-counter, e restituendo questa funzione interna siamo in grado di accedere ai dati disponibili per contrastare quando è stato definito. Questa informazione è privata a questa istanza di MyCounter - se dovessimo creare un altro contatore, che avrebbe utilizzato un posto diverso per memorizzare il conteggio interno. Continuando dall'esempio precedente:

(define mycounter2 (make-counter))

(mycounter2)                      ; returns 1

(mycounter)                       ; returns 3

Altri suggerimenti

E 'utile per la ricorsione, quando c'è solo 1 metodo che mai chiamarlo

string[] GetFiles(string path)
{
  void NestedGetFiles(string path, List<string> result)
  {
    result.AddRange( files in the current path);
    foreach(string subPath in FoldersInTheCurrentPath)
      NestedGetFiles(subPath, result);
  }

   List<string> result = new List<string>();
   NestedGetFiles(path, result);
   return result.ToArray();
}

Il codice di cui sopra è completamente composto, ma si basa su C # per dare l'idea di ciò che intendo. L'unico metodo che può chiamare NestedGetFiles è il metodo GetFiles.

Una funzione nidificata è solo una funzione all'interno di un'altra funzione.

Sì, si tratta di un risultato di tutto essere un oggetto. Dal momento che si può avere variabili visibili solo nel campo di applicazione della funzione di variabili e può puntare a funzioni si può avere una funzione a cui fa riferimento una variabile locale.

Non credo che ci sia qualcosa che si può fare con una funzione annidata che assolutamente non si poteva fare a meno. Un sacco di volte ha senso, però. Vale a dire, ogni volta che una funzione è un "sub-funzione" di qualche altra funzione.

Un caso d'uso comune per me è quando una funzione esegue un sacco di logica complicato, ma ciò che la funzione calcola / rendimento è facile astratta per tutti i casi dettati dalla logica.

(C#) :Lo uso per semplificare la visualizzazione del browser oggetti e per strutturare meglio le mie classi.Come classe Ruota annidata nella classe Camion.

Non dimenticare questo dettaglio:"I tipi nidificati possono accedere ai membri privati ​​e protetti del tipo che li contiene, inclusi eventuali membri privati ​​o protetti ereditati."

funzioni nidificate consentono di incapsulare il codice che è rilevante solo per il funzionamento interno di una funzione all'interno di tale funzione, pur consentendo di separare il codice per leggibilità o generalizzazione. In alcune implementazioni, consentono anche l'accesso al perimetro esterno. In D:

int doStuff() {
    int result;
    void cleanUpReturn() {
        myResource1.release();
        myResource2.release();
        return result * 2 + 1;
    }

    auto myResource1 = getSomeResource();
    auto myResource2 = getSomeOtherResource();
    if(someCondition) {
        return cleanUpReturn();
    } else {
        doSomeOtherStuff();
        return cleanUpReturn();
    }
}

Naturalmente, in questo caso, questo potrebbe anche essere maneggiata con Raii, ma è solo un semplice esempio.

Possono anche essere utile se avete bisogno di passare una funzione ad un'altra funzione come argomento. Possono anche essere utile per fare le funzioni di fabbrica per le funzioni di fabbrica (in Python):

>>> def GetIntMaker(x):
...   def GetInt():
...     return x
...   return GetInt
... 
>>> GetInt = GetIntMaker(1)
>>> GetInt()
1

Una funzione nidificata è semplicemente una funzione definita all'interno del corpo di un'altra funzione. Perché? Circa l'unico motivo che mi veniva in mente la parte superiore della mia testa è una funzione di supporto o utilità.

Questo è un esempio inventato ma tenere con me. Diciamo che ha avuto una funzione che doveva agire sui risultati di due interrogazioni e riempire un oggetto con i valori da una delle query. Si potrebbe fare qualcosa di simile alla seguente.

function process(qryResult q1, qryResult q2) {

   object o;
   if (q1.someprop == "useme") {
       o.prop1 = q1.prop1;
       o.prop2 = q1.prop2;
       o.prop3 = q1.prop3;
   } else if (q2.someprop == "useme") {
       o.prop1 = q2.prop1;
       o.prop2 = q2.prop2;
       o.prop3 = q2.prop3;
   }

   return o;

}

Se trovassi 20 strutture, si sta duplicare il codice per impostare l'oggetto più e più volte che conduce a una funzione enorme. Si potrebbe aggiungere una semplice funzione annidata eseguire la copia delle proprietà della query per l'oggetto. In questo modo:

function process(qryResult q1, qryResult q2) {

   object o;
   if (q1.someprop == "useme") {
       fillObject(o,q1);
   } else if (q2.someprop == "useme") {
       fillObject(o,q2);
   }

   return o;

   function fillObject(object o, qryResult q) {
       o.prop1 = q.prop1;
       o.prop2 = q.prop2;
       o.prop3 = q.prop3;
   }


}

Si mantiene le cose un po 'più pulito. Essa non deve essere una funzione annidata? No, ma si consiglia di farlo in questo modo, se la funzione di processo è l'unico che avrebbe dovuto fare questa copia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top