La programmazione funzionale è solo diversa, o è davvero più difficile?

12

La programmazione funzionale è appena diversa , o in realtà è più difficile ?

Dì qualcuno che non ha mai imparato la programmazione prima d'ora, e che viene insegnato alla programmazione funzionale. rispetto a qualcuno che non ha mai imparato prima la programmazione, e viene insegnato alla programmazione imperativa. quale troverà più duro? o lo stesso?

La mia domanda: dì che il problema ora è quello di cammellare-caso un input,

tale che qwe_asd_zxc_rty_fgh_vbn diventa qweAsdZxcRtyFghVbn

Il modo procedurale è:

  1. dividerlo lungo il _
  2. passa attraverso l'array saltando il primo elemento
  3. per ogni voce si capitalizza la prima lettera
  4. unisci i risultati insieme

Il modo funzionale è:

  1. se non riesci a trovare _ return input
  2. taglia il input lungo il primo _ (tale da ottenere qwe e asd_zxc_rty_gfh_cvb )
  3. capitalizza la prima lettera di head e concatala con f(tail)

Ok se hai uno background funzionale e hai una notevole esperienza nella programmazione procedurale, vorrei chiedere: ci vorrà più tempo per capire il modo procedurale o ci vorrà più tempo per per capire il modo funzionale?

Se hai uno background procedurale ma hai molti anni di esperienza con la programmazione funzionale, vorrei porre la stessa domanda: ti ci vorrà più tempo per capire il modo procedurale o ci vuole più tempo per capire il modo funzionale?

    
posta Pacerier 10.06.2011 - 06:24
fonte

5 risposte

12

Semplicemente diverso. La programmazione funzionale è molto più strettamente correlata alla matematica, che la maggior parte delle persone conosce. L'intera cosa delle "variabili immutabili" è solo uno shock per i programmatori imperativi in cui la mentalità "mutevole" è profondamente radicata.

Per i nuovi arrivati, è spesso abbastanza intuitivo che non puoi semplicemente cambiare il valore di qualcosa.

Dove ho studiato CS, ci è stato insegnato un linguaggio funzionale come il nostro primo corso. E tutti coloro che avevano imparato C ++ o Java in precedenza avevano difficoltà a farlo. Quelli che erano nuovi alla programmazione lo hanno scelto abbastanza facilmente.

    
risposta data 10.06.2011 - 10:20
fonte
20

È solo diverso

Quando programmate di tradurre essenzialmente il modo in cui ragionate in codice, la distanza tra i vostri pensieri e la soluzione finale potrebbe essere definita come il "divario cognitivo". Più grande è il divario, più difficile sarà il tuo bridge.

Se vieni da un background procedurale ti sarai allenato a pensare in modo procedurale, quindi il gap sarà inferiore al codice funzionale, e viceversa.

L'unico modo per un paradigma di programmazione di essere intrinsecamente più semplice di qualsiasi altra cosa sarebbe se fosse mappato su qualcosa che già conoscevi, come un linguaggio normale, quindi avresti iniziato con un intervallo più breve.

Funzionale e procedurale è comunque un concetto piuttosto fluido e tendono a sovrapporsi

    
risposta data 10.06.2011 - 08:11
fonte
4

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.

    
risposta data 10.06.2011 - 07:16
fonte
4

Ecco il codice completo in Racket :

;; camelize : string -> string
(define (camelize str)
  (let ([parts (regexp-split #rx"_" str)])
    ;; result of regexp-split is never empty
    (apply string-append
           (first parts)
           (map string-titlecase (rest parts)))))

(camelize "qwe_asd_zxc_rty_fgh_vbn")
;; => "qweAsdZxcRtyFghVbn"

Come programmatore funzionale con esperienza procedurale, non penso che mi occorrerà più tempo per "capire" una soluzione procedurale, ma mi richiederebbe più tempo per digitarla.

BTW, l'esempio di risultato previsto nel post originale è errato: manca una "h" vicino alla fine.

    
risposta data 10.06.2011 - 09:17
fonte
3

La mia teoria preferita è che i modelli di programmazione sono più facili da capire quanto più sono vicini al funzionamento effettivo dei computer. I puntatori sono difficili da capire finché non ti accorgi che sono essenzialmente indirizzi di macchine. La ricorsione è difficile da comprendere finché non si è consapevolmente passati a un piccolo esempio, si sono visti i frame dello stack e si è realizzato dove sono memorizzati i diversi valori della stessa variabile. Ciò non significa che la programmazione degli assemblatori sia più facile della programmazione ad alto livello, ma aver visto come è fatto fa miracoli per il modello mentale che è la chiave per la competenza, sia in termini di programmazione che di usabilità generale.

Ora, il modello procedurale è in qualche modo più vicino alla solita architettura della macchina: le assegnazioni sono scritture di memoria (o registro). Le chiamate di procedure sono in realtà solo salti di fantasia, un if è in realtà un salto condizionato, ecc. Ma in Lisp, ad esempio, non esiste un semplice equivalente di basso livello a un binding lessicale oa un'espressione lambda. Comprenderlo richiede di immaginare una macchina funzionale astratta completamente separata tra il livello linguistico e la macchina fisica, perché e apparentemente la maggior parte della gente non arriva mai così lontano.

(I sono familiare con l'idea che l'architettura di von Neumann sia in definitiva arbitraria, e non dovremmo pregiudicare le menti dei principianti con dettagli irrilevanti dell'architettura della macchina, e invece introdurli direttamente alla semantica dei linguaggi di programmazione, infatti, ho insegnato personalmente alcuni corsi di questo tipo, ma sempre più ritengo che questo sia un obiettivo nobile ma fuorviante: le persone imparano la programmazione costruendo la comprensione dal basso verso l'alto, e il modo di programmazione funzionale è semplicemente un po ' più a lungo.)

    
risposta data 10.06.2011 - 09:10
fonte