Questa è una domanda generica sull'uso di funzioni anonime come argomenti ad altre funzioni. Do un esempio in Python, ma la domanda non riguarda Python (e sono particolarmente interessato a sapere se le risposte potrebbero essere diverse per i linguaggi funzionali rispetto ad altri paradigmi).
In Python è comune passare una funzione anonima come argomento ad un'altra funzione, ad esempio:
sorted(my_data_structure, key=lambda x: x[0].foo)
dove lambda x: x[0].foo
è una funzione anonima per restituire l'attributo foo
dell'elemento 0 di ogni cosa in my_data_structure
(supponendo che qualsiasi cosa viva in my_data_structure
avrà un elemento 0th e che l'elemento 0th sarà avere un attributo foo
).
A mio parere, in tutti i casi tranne i più semplici, questo presenta un problema per l'incapsulamento e l'estensibilità: cosa succede se my_data_structure
cambia? Cosa succede se l'attributo da ordinare diventa bar
in un successivo refactoring del codice? Ora devi scendere nell'effettivo lambda
per gestirlo.
In alternativa, questo potrebbe essere stato scritto come:
def my_helper(some_data_thing):
"""My intentions are ____ !
"""
return some_data_thing[0].foo
#Elsewhere in the code:
sorted(my_data_structure, key=my_helper)
Mentre questo aggiunge 4 linee di codice, è più leggibile. Non devi analizzare ciò che lambda
sta cercando di fare nel momento in cui leggi la chiamata a sorted
. Fornisce l'opportunità per l'annotazione del tipo, la documentazione o anche il test dell'unità per la funzione di supporto.
Se qualcosa cambia, ma vuoi comunque che il codice locale intorno all'uso di sorted
rimanga lo stesso, questo incapsula piacevolmente per te nella funzione di aiuto. E se più di un posto è necessario per ordinare, o raggruppare, o qualsiasi altra cosa, con la stessa chiave, ottieni il riutilizzo del codice meglio di quello che riproducendo il lambda
è molte posizioni.
Tuttavia, altri potrebbero anche dire che ti stai piegando all'indietro per dare un nome, my_helper
, ad una piccola funzione che è in realtà più chiara per vederlo direttamente nel codice.
Posso essere d'accordo con questo, in particolare quando il lambda
coinvolto è molto piccolo, ma cosa succede se deve essere un multi-line lambda
che si imbatte in molti problemi di indentazione, o coinvolge un po ' comprensione dell'elenco offuscata o qualche altro dispositivo?
La mia domanda è: quali approcci esistono per determinare dove tracciare la linea tra un'utile funzione anonima in linea che è "autosufficiente" abbastanza da rendere più efficace la scrittura diretta rispetto a una funzione in linea che è troppo complesso e dovrebbe essere avvolto in una funzione di supporto. Ci sono altre considerazioni che non sto prendendo in considerazione?
Ad esempio: questo post su questo problema in JavaScript afferma e afferma molte delle preoccupazioni che ho elencati. È codificato per la programmazione in generale? È un linguaggio o un paradigma specifico? E che dire dell'altra faccia del dibattito?