Domanda

Nella programmazione funzionale, è spesso importante ottimizzare qualsiasi " looping " codice per essere ricorsivo di coda. Gli algoritmi ricorsivi di coda sono generalmente divisi tra due funzioni, una che imposta il caso base e un'altra che implementa il ciclo reale. Un buon esempio (anche se accademico) sarebbe la funzione inversa.

reverse :: [a] -> [a]
reverse = reverse_helper []

reverse_helper :: [a] -> [a] -> [a]
reverse_helper result [] = result
reverse_helper result (x:xs) = reverse_helper (x:result) xs

" reverse_helper " non è davvero un buon nome descrittivo. Tuttavia, " reverse_recursive_part " è solo imbarazzante.

Quale convenzione di denominazione useresti per funzioni di supporto come questa?

È stato utile?

Soluzione

Tendo ad aggiungere " _recurse " all'estremità. Quindi " reverse_recurse " ;. Non sono sicuro da dove l'ho preso. Mi piace lasciare la funzione del case base semplice come nel tuo esempio. Tende ad essere il "pubblico" e il fatto che utilizzi una funzione di supporto per eseguire l'iterazione è irrilevante per il chiamante. In javascript a volte vado al punto di nascondere la funzione iterativa tramite una chiusura, per chiarire davvero che non deve essere chiamato direttamente.

Altri suggerimenti

Puoi chiamare la funzione helper come preferisci, e non importerà fino a quando non metterai la funzione helper in " global " namespace. Aggiungendo semplicemente un "primo" sembra una pratica comune. :) Ad esempio, in Haskell,

reverse :: [a] -> [a]
reverse = reverse' []
    where reverse' :: [a] -> [a] -> [a]
          reverse' result [] = result
          reverse' result (x:xs) = reverse' (x:result) xs

Uso sempre do_, come " do_compute " con "calcola". Lo trovo abbastanza descrittivo in quanto è effettivamente la parte della funzione che esegue l'azione, mentre il "calcolo" che viene chiamato deve avere un nome descrittivo semplice per il mondo esterno.

Sono d'accordo con ShreevatsaR, se non si fa in modo che l'helper funzioni di primo livello (o peggio, lo si metta nella lista di esportazione), non importa quale sia il suo nome. Tendo a chiamare le funzioni di supporto f e g .

reverse :: [a] -> [a]
reverse = f []
  where
    f ys []     = xs
    f ys (x:xs) = f (x:ys) xs

Uso questo schema di denominazione solo per piccole funzioni (altrimenti non so a cosa si riferisca f ). Inoltre, perché mai dovresti scrivere grandi funzioni?

Tuttavia, se vuoi esportare la tua funzione 'helper' perché potrebbe essere utile ad altri, la chiamerei:

reverseAccumulator

Come zip e zipWith di Haskell. Ma non chiamerei quelle funzioni 'helper', zipWith è solo una funzione generica e zip è l'implementazione predefinita (probabilmente quella che viene usata di più).

Concordo anche con ShreevatsaR, in questo esempio renderei l'helper una funzione privata.

Per gli altri casi in cui ho bisogno che le funzioni di supporto siano visibili nell'intero modulo, ma non esportate, tendo a mettere in prefisso le funzioni con '_'. Certo, c'è la dichiarazione esplicita delle esportazioni ma durante lo sviluppo tendo ad esportare tutte le funzioni per facilitare l'esplorazione interattiva, ad es. in ghci. Più tardi aggiungo l'elenco delle funzioni esportate e la barra inferiore rende facile ricordare se intendevo che una funzione fosse locale o meno.

Uso aux o foo_aux (per la funzione principale foo ) e annido la definizione in modo che non sia visibile esternamente.

installa ed esegui

Esempio:

function whateverSetup() { ... }
function whateverExecute() { ... }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top