I comuni linguaggi di pro­gram­ma­zio­ne di solito con­sen­to­no di di­stin­gue­re tra diversi paradigmi di pro­gram­ma­zio­ne, in par­ti­co­la­re tra pro­gram­ma­zio­ne di­chia­ra­ti­va e im­pe­ra­ti­va. In parole povere, tali paradigmi sono l’approccio di base nella pro­gram­ma­zio­ne di un software. Un sot­toin­sie­me dell’approccio di­chia­ra­ti­vo è la co­sid­det­ta pro­gram­ma­zio­ne fun­zio­na­le, che viene uti­liz­za­ta in par­ti­co­la­re nello sviluppo dei seguenti programmi o codici:

  • Ap­pli­ca­zio­ni tecniche e ma­te­ma­ti­che
  • In­tel­li­gen­za Ar­ti­fi­cia­le (IA)
  • Com­pi­la­to­ri e parser
  • Algoritmi

Cosa rende l’approccio dei linguaggi di pro­gram­ma­zio­ne fun­zio­na­li così in­te­res­san­te per questo tipo di ap­pli­ca­zio­ni in­for­ma­ti­che? E qual è la dif­fe­ren­za rispetto ad altri concetti come la pro­gram­ma­zio­ne orientata agli oggetti?

Cos’è la pro­gram­ma­zio­ne fun­zio­na­le?

Come sug­ge­ri­sce il nome, l’approccio fun­zio­na­le nella pro­gram­ma­zio­ne si concentra sulle funzioni. In un programma fun­zio­na­le, tutti gli elementi possono essere intesi come funzioni e il codice può essere eseguito tramite richieste di funzioni se­quen­zia­li. Al contrario, non ci sono as­se­gna­zio­ni autonome di valori. Una funzione può essere con­si­de­ra­ta come una versione speciale di una sub­rou­ti­ne. Questa è riu­ti­liz­za­bi­le e, a dif­fe­ren­za di una procedura, re­sti­tui­sce di­ret­ta­men­te il risultato.

Na­tu­ral­men­te, in molti linguaggi di pro­gram­ma­zio­ne spe­cia­liz­za­ti ci sono funzioni che vengono definite e poi uti­liz­za­te. Non è questo, dunque, il tratto di­stin­ti­vo della pro­gram­ma­zio­ne fun­zio­na­le. Ciò che rende tale approccio così im­por­tan­te per l’in­for­ma­ti­ca e allo stesso tempo così versatile è il fatto che le funzioni possono assumere “strutture” diverse. Ad esempio, possono essere collegate tra loro come dati, uti­liz­za­te come parametri e anche come risultati fun­zio­na­li. Questo trat­ta­men­to speciale delle funzioni permette ai pro­gram­ma­to­ri di im­ple­men­ta­re ed elaborare compiti di calcolo di ampia portata (spe­cial­men­te quelli di natura simbolica).

Perché la pro­gram­ma­zio­ne fun­zio­na­le è così im­por­tan­te oggi

Anche se le radici della pro­gram­ma­zio­ne fun­zio­na­le risalgono agli anni '30 (come parte della ricerca ma­te­ma­ti­ca di base), l’approccio fun­zio­na­le gode ancora di grande po­po­la­ri­tà, so­prat­tut­to in campo tecnico e ma­te­ma­ti­co. Le ragioni sono mol­te­pli­ci:

  • Ampie pos­si­bi­li­tà di tra­sfor­ma­zio­ne del programma algebrico
  • Ampie pos­si­bi­li­tà di sintesi del programma algebrico
  • Semplici opzioni di analisi semantica grazie all’eli­mi­na­zio­ne degli “stati interni nel processo di calcolo” e degli “effetti col­la­te­ra­li”.
  • Eli­mi­na­zio­ne degli stati interni: a dif­fe­ren­za della pro­gram­ma­zio­ne im­pe­ra­ti­va, non sono necessari stati interni di un processo di calcolo.
  • Nessun effetto col­la­te­ra­le: con il metodo fun­zio­na­le si possono eliminare anche i cam­bia­men­ti di stato ap­par­te­nen­ti agli stati interni, cioè i co­sid­det­ti effetti col­la­te­ra­li.

La pro­gram­ma­zio­ne fun­zio­na­le offre un alto grado di astra­zio­ne perché si basa sul concetto ma­te­ma­ti­co e sul principio di fun­zio­na­men­to. Se usata ade­gua­ta­men­te, questo tipo di pro­gram­ma­zio­ne permette di ottenere un codice molto preciso. Grazie al maggior numero possibile di unità piccole, ri­pe­tu­ta­men­te uti­liz­za­bi­li e molto spe­cia­liz­za­te, per l’appunto le funzioni, viene fornito un programma per la ri­so­lu­zio­ne di un compito so­stan­zial­men­te più complesso.

Ci sono quindi numerose ragioni pratiche per cui la pro­gram­ma­zio­ne fun­zio­na­le e i relativi linguaggi di pro­gram­ma­zio­ne occupano ancora oggi una posizione speciale nell’ambito dell’in­for­ma­ti­ca, spe­cial­men­te quando si tratta di compiti ma­te­ma­ti­ci complessi e algoritmi. Le aree di ap­pli­ca­zio­ne molto speciali fanno sì che i linguaggi di pro­gram­ma­zio­ne fun­zio­na­le siano piuttosto di nicchia.

In sintesi: i linguaggi di pro­gram­ma­zio­ne fun­zio­na­le più im­por­tan­ti

Tra i più im­por­tan­ti linguaggi di pro­gram­ma­zio­ne basati sull’approccio fun­zio­na­le vi sono:

  • LISP
  • ML
  • Haskell
  • OCaml
  • F#
  • Erlang
  • Clojure
  • Scala

Inoltre, ci sono altri noti linguaggi di pro­gram­ma­zio­ne che con­sen­to­no di scegliere la pro­gram­ma­zio­ne fun­zio­na­le tra i diversi paradigmi possibili:

  • Perl
  • Ruby
  • Visual Basic .NET
  • Dylan
  • EC­MA­Script

Tabella rias­sun­ti­va con vantaggi e svantaggi della pro­gram­ma­zio­ne fun­zio­na­le

Vantaggi Svantaggi
Programmi stateless I dati (es. variabili) non possono essere mo­di­fi­ca­ti
Adatto per la pa­ral­le­liz­za­zio­ne Recupero di grandi quantità di dati non ef­fi­cien­te
Codice fa­cil­men­te testabile Non con­si­glia­to per le con­nes­sio­ni a database e server
Codice fa­cil­men­te ve­ri­fi­ca­bi­le, possono essere ve­ri­fi­ca­te anche le funzioni stateless Non adatto a molte ri­cor­sio­ni dello stesso stack
Com­bi­na­bi­le con la pro­gram­ma­zio­ne im­pe­ra­ti­va, orientata agli oggetti La pro­gram­ma­zio­ne ricorsiva può portare a gravi errori
Codice più preciso e più breve Non adatto a tutti i compiti

La tabella può indicarvi se il paradigma fun­zio­na­le possa essere o meno l’approccio ap­pro­pria­to per la pro­gram­ma­zio­ne di un progetto software. La decisione a favore di uno stile di pro­gram­ma­zio­ne dipende spesso dalle pre­fe­ren­ze personali dello svi­lup­pa­to­re. Ad esempio, la pro­gram­ma­zio­ne orientata agli oggetti come al­ter­na­ti­va concreta all’approccio fun­zio­na­le è molto diffusa tra i pro­gram­ma­to­ri. Di seguito, trovate un confronto tra i due approcci con un esempio pratico con­clu­si­vo.

Una tendenza? Pro­gram­ma­zio­ne orientata agli oggetti e pro­gram­ma­zio­ne fun­zio­na­le a confronto

Come nel mondo della moda, anche nella pro­gram­ma­zio­ne ci sono delle tendenze: da tempo ormai, la pro­gram­ma­zio­ne orientata agli oggetti, so­prat­tut­to nello sviluppo di ap­pli­ca­zio­ni Web e giochi per computer, è molto popolare. Rispetto alla pro­gram­ma­zio­ne fun­zio­na­le, questo approccio non descrive i singoli elementi come funzioni, ma come oggetti e classi. In com­bi­na­zio­ne con un sistema di eredità, tutti i com­po­nen­ti possono essere riu­ti­liz­za­ti ed estesi in qualsiasi momento e senza problemi. D’altra parte, il codice fun­zio­na­le è molto più snello, più chiaro e par­ti­co­lar­men­te van­tag­gio­so quando è ne­ces­sa­rio un codice testabile e ve­ri­fi­ca­bi­le.

Tra l’altro, in alcuni casi non serve scegliere quale approccio di pro­gram­ma­zio­ne adottare: molti linguaggi di pro­gram­ma­zio­ne moderni sup­por­ta­no il lavoro con i due paradigmi, in modo che possano essere fa­cil­men­te combinati e che si possa trarre vantaggio da entrambi.

Pro­gram­ma­zio­ne fun­zio­na­le nell’esempio di un parser

I parser sono elementi centrali in tutti i programmi per computer. Sono spesso in­di­spen­sa­bi­li, poiché traducono il lin­guag­gio di pro­gram­ma­zio­ne in lin­guag­gio macchina.

Un parser può essere im­ple­men­ta­to fon­da­men­tal­men­te sulla base di diversi paradigmi di pro­gram­ma­zio­ne, per esempio con un lin­guag­gio orientato agli oggetti. Tuttavia, l’approccio fun­zio­na­le può offrire una serie di vantaggi utili:

  • non esistono variabili globali e mutevoli. Di con­se­guen­za, non ci sono errori di pro­gram­ma­zio­ne derivanti dal co­sid­det­to “mutable global state”, come può essere il caso dei progetti orientati agli oggetti. Un parser ne trae vantaggio in qualità di elemento centrale del programma.
  • Grazie alle funzioni di ordine superiore e al codice di programma chiaro, è possibile gestire fa­cil­men­te anche raccolte di dati più grandi. Questo è molto van­tag­gio­so per un parser, che na­tu­ral­men­te deve elaborare grandi quantità di dati.
  • Un parser è un elemento di programma eseguito molto fre­quen­te­men­te. Perciò, è par­ti­co­lar­men­te ne­ces­sa­rio che sia pro­gram­ma­to con pre­ci­sio­ne e che funzioni in modo ef­fi­cien­te, come nel caso della pro­gram­ma­zio­ne fun­zio­na­le.
  • Un errore nel processo di parsing è so­li­ta­men­te fatale e deve essere evitato il più possibile. Tuttavia, mentre un programma è in ese­cu­zio­ne, sorgono ine­vi­ta­bil­men­te numerose di­pen­den­ze se­man­ti­che, che possono portare a gravi errori, spesso solo dopo un tempo di ese­cu­zio­ne più lungo. Una pro­gram­ma­zio­ne fun­zio­na­le cor­ret­ta­men­te im­ple­men­ta­ta può aiutare a ridurre al minimo o a prevenire com­ple­ta­men­te questi gravi errori di ese­cu­zio­ne.
Vai al menu prin­ci­pa­le