[functional-programming] Qual è la differenza tra programmazione procedurale e programmazione funzionale?



6 Answers

Fondamentalmente i due stili sono come Yin e Yang. Uno è organizzato, mentre l'altro caotico. Ci sono situazioni in cui la programmazione funzionale è la scelta più ovvia, e in altre situazioni la programmazione procedurale è la scelta migliore. Questo è il motivo per cui ci sono almeno due lingue che sono recentemente uscite con una nuova versione, che abbraccia entrambi gli stili di programmazione. ( Perl 6 e D 2 )

Procedurale:

  • L'output di una routine non ha sempre una correlazione diretta con l'input.
  • Tutto è fatto in un ordine specifico.
  • L'esecuzione di una routine può avere effetti collaterali.
  • Tende ad enfatizzare le soluzioni di implementazione in modo lineare.

Perl 6

sub factorial ( UInt:D $n is copy ) returns UInt {

  # modify "outside" state
  state $call-count++;
  # in this case it is rather pointless as
  # it can't even be accessed from outside

  my $result = 1;

  loop ( ; $n > 0 ; $n-- ){

    $result *= $n;

  }

  return $result;
}

D 2

int factorial( int n ){

  int result = 1;

  for( ; n > 0 ; n-- ){
    result *= n;
  }

  return result;
}

Funzionale:

  • Spesso ricorsivo.
  • Restituisce sempre la stessa uscita per un dato input.
  • L'ordine di valutazione è solitamente indefinito.
  • Deve essere apolide. cioè nessuna operazione può avere effetti collaterali.
  • Adatto per l'esecuzione parallela
  • Tende a enfatizzare un approccio dividi e conquista.
  • Può avere la caratteristica di Lazy Evaluation.

Haskell

(copiato da Haskell );

fac :: Integer -> Integer

fac 0 = 1
fac n | n > 0 = n * fac (n-1)

o in una riga:

fac n = if n > 0 then n * fac (n-1) else 1

Perl 6

proto sub factorial ( UInt:D $n ) returns UInt {*}

multi sub factorial (  0 ) { 1 }
multi sub factorial ( $n ) { $n * samewith $n-1 } # { $n * factorial $n-1 }

D 2

pure int factorial( invariant int n ){
  if( n <= 1 ){
    return 1;
  }else{
    return n * factorial( n-1 );
  }
}

Nota a margine:

Factorial è in realtà un esempio comune per mostrare quanto sia facile creare nuovi operatori in Perl 6 nello stesso modo in cui si crea una subroutine. Questa caratteristica è così radicata in Perl 6 che la maggior parte degli operatori nell'implementazione Rakudo sono definiti in questo modo. Consente inoltre di aggiungere i propri candidati multipli agli operatori esistenti.

sub postfix:< ! > ( UInt:D $n --> UInt )
  is tighter(&infix:<*>)
  { [*] 2 .. $n }

say 5!; # 120␤

Questo esempio mostra anche la creazione dell'intervallo ( 2..$n ) e il meta-operatore di riduzione dell'elenco ( [ OPERATOR ] LIST ) in combinazione con l'operatore di moltiplicazione numerico infisso. ( * )
Mostra anche che puoi mettere --> UInt nella firma invece di returns UInt dopo di esso.

(Puoi farla franca con l'avvio dell'intervallo con 2 poiché il moltiplicatore "operatore" restituirà 1 quando chiamato senza argomenti)

Question

Ho letto gli articoli di Wikipedia sia per la programmazione procedurale sia per la programmazione funzionale , ma sono ancora un po 'confuso. Qualcuno potrebbe bollirlo fino al midollo?




Una programmazione funzionale è identica alla programmazione procedurale in cui le variabili globali non vengono utilizzate.




I linguaggi procedurali tendono a tenere traccia dello stato (usando le variabili) e tendono ad essere eseguiti come una sequenza di passaggi. I linguaggi puramente funzionali non tengono traccia dello stato, usano valori immutabili e tendono ad essere eseguiti come una serie di dipendenze. In molti casi lo stato dello stack di chiamate contiene le informazioni che sarebbero equivalenti a quelle che verrebbero memorizzate nelle variabili di stato nel codice procedurale.

La ricorsione è un classico esempio di programmazione in stile funzionale.




La programmazione procedurale divide le sequenze di istruzioni e costrutti condizionali in blocchi separati chiamati procedure parametrizzate su argomenti che sono valori (non funzionali).

La programmazione funzionale è la stessa eccetto che le funzioni sono valori di prima classe, quindi possono essere passati come argomenti ad altre funzioni e restituiti come risultati dalle chiamate di funzione.

Si noti che la programmazione funzionale è una generalizzazione della programmazione procedurale in questa interpretazione. Tuttavia, una minoranza interpreta la "programmazione funzionale" come "senza effetti collaterali" che è alquanto diversa ma irrilevante per tutti i principali linguaggi funzionali, ad eccezione di Haskell.




Per espandere il commento di Konrad:

e l'ordine di valutazione non è ben definito

Alcuni linguaggi funzionali hanno quella che viene chiamata valutazione pigra. Il che significa che una funzione non viene eseguita finché non è necessario il valore. Fino a quel momento la funzione stessa è ciò che viene passato in giro.

I linguaggi procedurali sono step 1 step 2 step 3 ... se nel passo 2 dici add 2 + 2, lo fa proprio allora. Nella valutazione pigra diresti aggiungere 2 + 2, ma se il risultato non viene mai usato, non lo farà mai.




Per espandere il commento di Konrad:

Di conseguenza, un programma puramente funzionale produce sempre lo stesso valore per un input e l'ordine di valutazione non è ben definito;

Per questo motivo, il codice funzionale è generalmente più facile da parallelizzare. Dato che non ci sono (generalmente) effetti collaterali delle funzioni, e (generalmente) semplicemente agiscono sui loro argomenti, molti problemi di concorrenza vanno via.

La programmazione funzionale viene anche utilizzata quando è necessario essere in grado di dimostrare che il codice è corretto. Questo è molto più difficile da fare con la programmazione procedurale (non facile con funzionale, ma ancora più semplice).

Disclaimer: non ho usato la programmazione funzionale da anni e solo di recente ho iniziato a guardarlo di nuovo, quindi potrei non essere completamente corretto qui. :)




Nell'informatica, la programmazione funzionale è un paradigma di programmazione che tratta il calcolo come la valutazione delle funzioni matematiche ed evita lo stato e i dati mutabili. Sottolinea l'applicazione delle funzioni, in contrasto con lo stile di programmazione procedurale che enfatizza i cambiamenti di stato.






Related