Sì, la programmazione funzionale tende a essere difficile da comprendere per molte persone (direi, specialmente quelle che sono già state esposte alla programmazione procedurale).
Direi anche che il tuo esempio di programmazione funzionale non è davvero un ottimo esempio di programmazione funzionale. Sta usando la ricorsione e semplicemente componendo un risultato invece di modificare lo stato, ma non molto di più.
Per ottenere un esempio migliore di programmazione funzionale, considera un problema più generale: piuttosto che "cerca un trattino basso e converti la prossima lettera in maiuscolo", considera questo solo un caso speciale di ricerca di un modello ed eseguendo alcuni codice arbitrario quando viene trovato.
Molte lingue lo supportano, ma per farlo richiedono che specifichiamo il modello come qualcosa di simile a un'espressione regolare. Le espressioni regolari, tuttavia, non sono niente più o meno di un linguaggio di programmazione per scopi speciali, e un'implementazione RE è un compilatore e / o un interprete per quella lingua. Il risultato della compilazione dell'IR è fondamentalmente una funzione che viene eseguita (in una macchina virtuale RE speciale) per abbinare l'espressione a qualche input.
In qualcosa come Perl, usi un linguaggio speciale per specificare il modello, e un compilatore speciale per convertire quella stringa in una sorta di cosa simile alla funzione, e un interprete speciale per prendere quella cosa simile a una funzione per eseguirla. In un linguaggio funzionale, in genere si utilizza la lingua stessa per specificare il modello e si utilizza il compilatore del linguaggio per produrre una funzione reale . Siamo in grado di generare quella funzione al volo (circa come possiamo compilare una RE quando vogliamo), ma quando lo facciamo, il risultato può essere eseguito come qualsiasi altra funzione nel linguaggio invece di aver bisogno di cose speciali per farlo.
Il risultato è che possiamo generalizzare il problema sopra relativamente facilmente. Invece di codificare hardly il "_" e il "maiuscolo" direttamente nella trasformazione, tuttavia, possiamo avere qualcosa del tipo:
s&r(pattern, transform, string) {
if (!pattern(string))
return string
else
return transform(matched part of string) + s&r(rest of string);
}
Ma, a differenza di qualcosa in cui specificiamo il pattern come RE, possiamo specificare il pattern direttamente come una funzione reale, e comunque usarlo, qualcosa del tipo:
my_pattern(string) return beginning(string) == '_';
E poi passiamo quella funzione agli s & r. Al momento, è una funzione piuttosto banale e l'abbiamo codificata interamente in modo statico. Un linguaggio funzionale diventa in gran parte interessante quando lo usiamo come possiamo RE, e generiamo al volo una funzione completamente nuova basata su qualcosa come l'input dell'utente, ma a differenza di un RE quella funzione non ha bisogno di un interprete RE speciale da eseguire - è solo una funzione normale come qualsiasi altra.