Programmazione

3.4569120287217 (1114)
Inviato da nono 28/02/2009 @ 11:04

Tags : programmazione, computer, high tech

ultime notizie
La Soavegel Francavilla programma la nuova stagione - Brundisium.net
Riparte, con rinnovato entusiasmo, la programmazione della Soavegel Basket Francavilla per la nuova stagione agonistica. Primo nodo sciolto è stata la scelta dell'allenatore. Da più parti il coach Olive veniva dato per partente per lidi prestigiosi....
Un eBook sulla programmazione di iPhone ed iPod touch - mobileblog.it
La programmazione sui cellulari, è un qualcosa che fa' la fortuna dei piccoli sviluppatori ma, soprattutto assicura un buon successo al futuro dei sistemi operativi mobili. Dopo i corsi di programmazione per iPhone ei video tutorial, vi presentiamo...
PUGLIA: ADEGUAMENTO EDIFICI SCOLASTICI, VIA LIBERA A PIANO ... - Libero-News.it
''Si tratta - spiega l'assessore al Diritto allo Studio Mimmo Lomelo - di un provvedimento di notevole valenza politica che, attuando gli impegni programmatici assunti in sede di programmazione triennale, ci consente un progresso significativo...
Programma nutrizionale, dieta della mamma e salute del bambino - Vita di Donna Community
Cerchiamo di capire come un 'programma nutrizionale' può aiutare a prevenire future patologie dieta-correlate. E' opinione scientifica da diverso tempo che la condizione nutrizionale presente mentre il bambino si sviluppa nel ventre materno e la...
Vitagliano a Patriciello: «Non si spara nel mucchio» - Il Tempo
Gestione dei fondi europei, l'assessore regionale alla programmazione Gianfranco Vitagliano replica all'europarlamentare Aldo Patriciello, che in un intervista a un giornale locale ha dichiarato che alcuni imprenditori avrebbero chiesto di far luce...
Cosa c'è di bello in tivù per i piccoli? - Corriere della Sera
Sempre su BoingTV, appuntamento con “TIP TIP”, la programmazione pensata per un pubblico prescolare. In onda in tre orari diversi alle 7, alle 12.30 e alle 19.30, dal lunedì al venerdì, “Tom & Jerry Kids”: il famosissimo duo con ciuccio e pannolino....
Introduzione alla programmazione parallela con Axum (5/5) - Programmazione.it
Vengono definiti due agent QuickSortAgent e PartitionAgent, quest'ultimo richiamato dal primo, il quale lancia ricorsivamente 2 agenti del suo stesso tipo; poiché gli agenti non sono definiti come writer, l'elaborazione avverrà con più agenti in...
Acr Messina. Programmazione societaria e iscrizione al prossimo ... - Tempo Stretto
Un incontro ufficialmente fissato per illustrare ulteriori sviluppi in merito alla programmazione societaria e sull'iscrizione al prossimo campionato. La conferenza era inizialmente stata fissata per mercoledì scorso, ma poi annullata in virtù...
TV: “DR HOUSE” INCANTA TUTTI, PROGRAMMA PIU' VISTO AL MONDO - Primaonline.it
Il dato e' stato elebaotrato dalla Eurodata Tv Worldwide, che prende in esame la programmazione e il successo in 66 Paesi per un totale di un miliardo e mezzo di telespettatori. Sul fonte delle commedie femminili, lo scettro va a 'Desperate Hosewives'...

Programmazione funzionale

In informatica, la programmazione funzionale è un paradigma di programmazione in cui il flusso di esecuzione del programma assume la forma di una serie di valutazioni di funzioni matematiche. Solitamente questo approccio viene usato maggiormente in ambiti accademici piuttosto che industriali. Il punto di forza principale di questo paradigma è la mancanza di effetti collaterali (side-effect) delle funzioni, il che comporta una più facile verifica della correttezza e della mancanza di bug del programma e la possibilità di una maggiore ottimizzazione dello stesso. Un uso particolare del paradigma, per l'ottimizzazione dei programmi, è quello di trasformare gli stessi per utilizzarli nella programmazione parallela.

La programmazione funzionale pone maggior accento sulla definizione di funzioni, rispetto ai paradigmi procedurali e imperativi, che invece prediligono la specifica di una sequenza di comandi da eseguire. In questi ultimi, i valori vengono calcolati cambiando lo stato del programma attraverso delle assegnazioni; un programma funzionale, invece, è immutabile: i valori non vengono trovati cambiando lo stato del programma, ma costruendo nuovi stati a partire dai precedenti.

Le funzioni matematiche sono molto potenti in termini di flessibilità ed analisi. Per esempio, se una funzione è idempotente e non ha effetti collaterali allora una chiamata a questa funzione che ha il suo stesso output come input (f(f(x))) può essere efficientemente computata con una singola chiamata alla funzione.

Questo tipo di funzioni hanno zero o più parametri e un singolo valore di ritorno. I parametri sono gli input della funzione ed il valore di ritorno è il suo output. La definizione di una funzione descrive come questa deve essere valutata (computata) in termini di altre funzioni. Per esempio, la funzione f(x) = x2 + 2 è definita in termini delle funzioni di potenza e addizione. Ad un certo punto della serie di chiamate a funzioni, il linguaggio metterà a disposizioni funzioni atomiche, cioè funzioni che non richiamano nessun'altra funzione.

In un linguaggio di programmazione funzionale, le funzioni possono essere manipolate in diversi modi. Solitamente, in questi linguaggi, le funzioni sono entità di prima classe, cioè possono essere passate come parametri ad altre funzioni e possono essere restituite come valori di ritorno da altre funzioni. Ciò permette a funzioni come mapcar in Lisp e map in Haskell, che prendono una funzione e una lista come input ed applicano la funzione in input ad ogni elemento della lista, di restituire una lista dei risultati. Le funzioni possono avere dei nomi, come in ogni altro linguaggio, o essere definite anonimamente (a volte anche a run-time) usando l'astrazione lambda, e essere usate come valori in altre funzioni.

I linguaggi funzionali permettono inoltre una tecnica chiamata currying, che permette di trasformare una funzione con parametri multipli in una funzione con un solo parametro che mappa ad un'altra funzione con un solo parametro e così via, fino all'esaurimento dei parametri. La funzione trasformata può essere applicata ad un sottoinsieme dei suoi parametri iniziali e dare come risultato una nuova funzione dove i parametri di quel sottoinsieme sono costanti e il resto dei parametri hanno valori non ancora specificati. Infine questa nuova funzione può essere applicata ai parametri rimanenti per ottenere il risultato finale. Per esempio, una funzione somma(x,y) = x + y può essere trasformata in modo tale che il valore di ritorno di somma(2) (nota che non c'è il parametro y) sia una funzione anonima equivalente alla funzione somma2(y) = 2 + y. Questa nuova funzione ha un solo parametro a cui somma 2. Questa tecnica non sarebbe possibile se le funzioni non fossero entità di prima classe.

Il Lambda calcolo può essere considerato il primo linguaggio di programmazione funzionale, anche se non fu progettato per essere eseguito su una macchina. Il Lambda calcolo è un modello di computazione progettato da Alonzo Church negli anni '30 che fornisce un modo molto formale di descrivere la valutazione di funzioni. Il primo linguaggio di programmazione funzionale, progettato per un computer, fu l'Information Processing Language (IPL), sviluppato da Newell, Shaw e Simon alla RAND Corporation per il computer JOHNNIAC, a metà degli anni '50. Un linguaggio funzionale molto migliorato fu il LISP, sviluppato da John McCarthy, mentre si trovava al Massachusetts Institute of Technology, per i computer della serie IBM 700/7000, alla fine degli anni '50. Anche se non era un linguaggio puramente funzionale, il LISP introdusse molte delle caratteristiche oggi trovate nei moderni linguaggi funzionali. Il linguaggio Scheme fu un successivo tentativo di semplificare e migliorare il LISP. Negli anni '70, all'Università di Edimburgo fu creato il linguaggio ML e all'Università di Kent David Turner creò il linguaggio Miranda. Il linguaggio Haskell fu creato e rilasciato alla fine degli anni '80 come tentativo di mettere insieme molte delle idee della ricerca sulla programmazione funzionale.

Se paragonata alla programmazione imperativa, può sembrare che la programmazione funzionale manchi di molti costrutti spesso (ma incorrettamente) ritenuti essenziali per un linguaggio imperativo, come il C o il Pascal. Per esempio, nella programmazione funzionale rigorosa, non c'è alcuna esplicita allocazione di memoria o assegnazione di variabile, ma, comunque, queste operazioni avvengono automaticamente quando una funzione è invocata: l'allocazione di memoria avviene per creare lo spazio necessario per i parametri e il valore di ritorno e l'assegnazione avviene per copiare i parametri nel nuovo spazio allocato e per copiare il valore di ritorno alla funzione chiamante. Entrambe le operazioni possono avvenire solo alla chiamata di una funzione e al ritorno da essa e quindi gli effetti collaterali sono eliminati. Eliminando gli effetti collaterali dalle funzioni, si ottiene ciò che viene chiamata trasparenza referenziale, che assicura che il risultato di una funzione sia lo stesso per uno stesso insieme di parametri, indifferentemente da quando e dove questa funzione venga valutata. La trasparenza referenziale rende molto più facile sia la dimostrazione della correttezza del programma sia l'identificazione automatica delle computazioni indipendenti per l'esecuzione parallela.

Le iterazioni, un altro costrutto della programmazione imperativa, sono ottenute attraverso il costrutto più generale delle chiamate ricorsive a funzioni. Le funzioni ricorsive invocano se stesse permettendo di eseguire più e più volte una stessa operazione. Può essere dimostrato che un'iterazione è equivalente ad uno speciale tipo di ricorsione chiamata tail recursion. La ricorsione nella programmazione funzionale può assumere molte forme e, in generale, è una tecnica più potente dell'iterazione. Per questa ragione, quasi tutti i linguaggi imperativi la supportano (con la notevole eccezione del Fortran 77 e del Cobol, prima del 2002).

I programmi puramente funzionali (cioè quelli che obbligano a rispettare le regole del non-effetto-collaterale, trasparenza referenziale, ecc., a differenza dei linguaggi non puramente funzionali che sono un ibrido tra paradigma funzionale e imperativo) non richiedono variabili e non hanno effetti collaterali e sono di conseguenza automaticamente thread-safe. Solitamente i linguaggi funzionali fanno un uso piuttosto sofisticato dello stack.

La programmazione funzionale fa un largo uso della ricorsione e, in alcuni linguaggi come Scheme, alcuni tipi di ricorsione (come la tail recursion) vengono riconosciuti e automaticamente ottimizzati dal compilatore.

Nei linguaggi di programmazione imperativi, generalmente, gli effetti collaterali nascosti sono la regola, non l'eccezione. Ogni volta che una procedura legge o scrive un valore da/in una variabile globale o condivisa, potenzialmente vi sono degli effetti collaterali nascosti. Questa mancanza di un preciso confine su cosa una funzione può modificare o meno porta ad un aumento della complessità nascosta dei programmi scritti in linguaggi non funzionali.

Rimuovendo questa mancanza di informazioni circa il dominio di una funzione, i linguaggi di programmazione funzionali offrono la possibilità di programmi più puliti che sono più facili da progettare e sottoporre a debugging. Comunque, questi non sono gli unici vantaggi.

Molti programmatori abituati ai paradigmi imperativi trovano difficile imparare la programmazione funzionale, la quale richiede un approccio nello scrivere i programmi completamente differente. Questa difficoltà insieme al fatto che gli ambienti dei linguaggi funzionali non hanno la stessa quantità di strumenti e librerie disponibili dei linguaggi tradizionali, sono tra le ragioni principali per cui la programmazione funzionale ha avuto poco utilizzo nell'industria del software. I linguaggi funzionali sono rimasti largamente di dominio accademico e hobbystico e quei linguaggi che hanno avuto un maggiore utilizzo sono linguaggi funzionali 'non puri', come l'Erlang e il Common Lisp. Si potrebbe dire che la maggiore influenza dei linguaggi funzionali sull'industria del software sia stata data da quei programmatori, nati in ambito accademico, che hanno usato lo stile di programmazione funzionale 'non puro' con i tradizionali linguaggi di programmazione imperativi.

Un potente meccanismo spesso utilizzato nella programmazione funzionale è quello delle funzioni di ordine superiore (o funzioni higher-order). Una funzione si dice di ordine superiore quando può prendere altre funzioni come parametri e/o restituire funzioni come risultato. L'operatore differenziale in matematica è un esempio di funzione che mappa una funzione ad un'altra funzione.

Le funzioni di ordine superiore erano studiate dalla teoria del lambda calcolo ben prima che la nozione di programmazione funzionale esistesse e sono presenti nel design di molti linguaggi di programmazione funzionali, quali lo Scheme e l'Haskell.

Più in generale si può dire che le funzioni di ordine superiore sono parte del linguaggio naturale. Per esempio, gli avverbi possono modificare i verbi (azioni) creando verbi derivati. Con lo stesso ragionamento si può dire che i verbi imperativi sono simili alle funzioni "ordinarie" dei linguaggi di programmazione.

Le funzioni di ordine superiore sono cruciali nel paradigma della programmazione a livello funzionale (da non confondere con la programmazione funzionale, di cui tratta questa voce), che include linguaggi come l'FP di John Backus e il J di Kenneth Eugene Iverson.

Questi compiti di basso livello erano il bound-checking, ovvero controllare i valori assunti dagli indici dei buffer per evitare overflow, il garbage collection, per la gestione della memoria e simili. Questi compiti sono parti essenziali dei programmi moderni e la loro sbagliata gestione è causa di buona parte dei bug del software, quali memory leak e vari tipi di overflow.

L'aumento delle prestazioni dei calcolatori ha tuttavia spostato l'attenzione della comunità informatica sullo sviluppo rapido del software, sulla sua correttezza e manutenibilità. Ciò ha facilitato l'introduzione di tecniche del tipo suddetto in linguaggi imperativi di uso comune. Ciò fa sì che oggi le performance dei linguaggi funzionali e dei linguaggi imperativi convergano. Per programmi che passano la maggior parte del tempo facendo computazioni numeriche, alcuni linguaggi funzionali (come l'Ocaml e il Clean) possono avvicinarsi alla velocità del C, mentre per programmi che gestiscono grandi matrici e basi di dati multidimensionali, i linguaggi funzionali ad array (come il J e il K) sono solitamente più veloci dei programmi C non ottimizzati. Comunque, i linguaggi puramente funzionali possono diventare considerevolmente più lenti di quelli imperativi quando manipolano grandi strutture dati, per via dell'utilizzo della memoria meno efficiente.

L'utilizzo della memoria nella programmazione funzionale può essere ottimizzato utilizzando delle strutture dati persistenti; queste strutture dati permettono ad una parte o alla totalità dei dati di essere condivisi con altri valori, rendendo la copia e la modifica relativamente economici. Queste operazioni vengono svolte in modo sicuro dato che queste strutture dati sono immutabili e di conseguenza non sorgono quelli che sono gli errori dovuti alla gestione dei puntatori, come invece avviene nelle strutture dati imperative. Tra le strutture dati persistenti comunemente usate vi sono le liste concatenate e gli alberi binari.

Le espressioni nei linguaggi funzionali possono essere valutate (computate) in due modi diversi: in modo 'rigoroso' (o anche 'eager' o 'strict') o in modo 'pigro' (o 'lazy'). I 'linguaggi rigorosi' computano tutti gli argomenti di una funzione prima di valutare la funzione stessa, mentre i 'linguaggi pigri' computano un argomento solamente quando questo è richiesto. L'Haskell è il più comune esempio di linguaggio pigro, mentre il linguaggio ML è rigoroso. La valutazione lazy è teoricamente meno efficiente di quella rigorosa, in quanto è richiesto all'esecutore del linguaggio di mantenere informazioni in merito agli argomenti valutati e non valutati. Tuttavia, è facile concepire percorsi di esecuzione nei quali, non venendo effettivamente usati uno o più argomenti, la tecnica lazy guadagna in velocità (ciò è in special modo verosimile quando gli argomenti di una funzione sono essi stessi chiamate ad altre funzioni, potenzialmente innestate a più livelli di profondità).

Le performance competitive dei moderni linguaggi funzionali (non puri) come l'Ocaml e l'SML ha portato alla loro adozione in aree di computazione scientifica storicamente dominate dal Fortran. Questi linguaggi moderni, grazie alla loro concisione ed espressività e grazie alla disposizione di sofisticate strutture dati e algoritmi, sono oggi utilizzati in vaste aree scientifiche, quali l'analisi numerica.

L'esempio più vecchio di linguaggio funzionale è il Lisp, anche se né il LISP originale né i Lisp moderni, come il Common Lisp, sono puramente funzionali. Le varianti del Lisp includono il Logo, lo Scheme e Dylan. Esempi di linguaggi funzionali moderni sono l'Haskell e i linguaggi della famiglia ML, quali ML e OCaml. Un altro linguaggio derivato da ML e' F#, sviluppato da Microsoft all'interno del framework .NET.

Altri sono l'Erlang, Mathematica, il Clean e Miranda.

Altri linguaggi, come per esempio Ruby, Python, Perl e TCL, possono essere usati in stile funzionale, dato che hanno funzioni di ordine superiore e altre astrazioni utili.

Oggi si sta cercando anche di sviluppare linguaggi di programmazione funzionali quantistici, cioè che possano esprimere algoritmi quantistici. Alcuni esempi sono il linguaggio di Peter Selinger (EN) qui descritto ed il linguaggio Haskell-like QML ((EN) homepage del progetto).

Questo articolo include parti di un articolo inserito su Nupedia il 19 giugno 2001: reviewed and approved by the Computers group; editor, Michael Witbrock; lead reviewer, Nancy Tinkham; lead copyeditors, Ruth Ifcher and Larry Sanger.

Per la parte superiore



Linguaggio di programmazione

Un codice python

In informatica, un linguaggio di programmazione è un linguaggio formale, dotato di una sintassi e di una semantica ben definite, utilizzabile per il controllo del comportamento di una macchina formale, o di una implementazione di essa (tipicamente, un computer).

Il primo linguaggio di programmazione della storia, se si esclude il linguaggio meccanico adoperato da Ada Lovelace per la programmazione della macchina di Charles Babbage, è a rigor di termini il Plankalkül di Konrad Zuse, sviluppato da lui nella svizzera neutrale durante la seconda guerra mondiale e pubblicato nel 1946. Plankalkül non venne mai realmente usato per programmare.

La programmazione dei primi elaboratori veniva fatta invece in Shortcode, da cui poi si è evoluto l'assembly, che costituisce una rappresentazione simbolica del linguaggio macchina. La sola forma di controllo di flusso è l'istruzione di salto condizionato, che porta a scrivere programmi molto difficili da seguire logicamente per via dei continui salti da un punto all'altro del codice.

La maggior parte dei linguaggi di programmazione successivi cercarono di astrarsi da tale livello basilare, dando la possibilità di rappresentare strutture dati e strutture di controllo più generali e più vicine alla maniera (umana) di rappresentare i termini dei problemi per i quali ci si prefigge di scrivere programmi. Tra i primi linguaggi ad alto livello a raggiungere una certa popolarità ci fu il Fortran, creato nel 1957 da John Backus, da cui derivò successivamente il BASIC (1964): oltre al salto condizionato, reso con l'istruzione IF, questa nuova generazione di linguaggi introduce nuove strutture di controllo di flusso come i cicli WHILE e FOR e le istruzioni CASE e SWITCH: in questo modo diminuisce molto il ricorso alle istruzioni di salto (GOTO), cosa che rende il codice più chiaro ed elegante, e quindi di più facile manutenzione.

Dopo la comparsa del Fortran nacquero una serie di altri linguaggi di programmazione storici, che implementarono una serie di idee e paradigmi innovativi: i più importanti sono l'ALGOL (1960) e il Lisp (1959). Tutti i linguaggi di programmazione oggi esistenti possono essere considerati discendenti da uno o più di questi primi linguaggi, di cui mutuano molti concetti di base; l'ultimo grande progenitore dei linguaggi moderni fu il Simula (1967), che introdusse per primo il concetto (allora appena abbozzato) di oggetto software.

Nel 1970 Niklaus Wirth pubblica il Pascal, il primo linguaggio strutturato, a scopo didattico; nel 1972 dal BCPL nascono prima il B (rapidamente dimenticato) e poi il C, che invece fu fin dall'inizio un grande successo. Nello stesso anno compare anche il Prolog, finora il principale esempio di linguaggio logico, che pur non essendo di norma utilizzato per lo sviluppo industriale del software (a causa della sua inefficienza) rappresenta una possibilità teorica estremamente affascinante.

Con i primi mini e microcomputer e le ricerche a Palo Alto, nel 1983 vede la luce Smalltalk, il primo linguaggio realmente e completamente ad oggetti, che si ispira al Simula e al Lisp: oltre a essere in uso tutt'oggi in determinati settori, Smalltalk viene ricordato per l'influenza enorme che ha esercitato sulla storia dei linguaggi di programmazione, introducendo il paradigma object-oriented nella sua prima incarnazione matura. Esempi di linguaggi object-oriented odierni sono Eiffel (1986), C++ (che esce nello stesso anno di Eiffel) e successivamente Java, classe 1995.

Programmare in un dato linguaggio di programmazione significa generalmente scrivere uno o più semplici file di testo ASCII, chiamato codice sorgente. I font, i colori e in generale l'aspetto grafico sono irrilevanti ai fini della programmazione in sé: per questo i programmatori non usano programmi di videoscrittura ma degli editor di testo (come emacs e brief) che invece offrono funzioni avanzate di trattamento testi (espressioni regolari, sostituzioni condizionali e ricerche su file multipli, possibilità di richiamare strumenti esterni ecc). Se un dato editor è in grado di lavorare a stretto contatto con gli altri strumenti di lavoro (compilatore, linker, interprete ecc.: vedi più avanti) allora più che di semplice editor si parla di IDE o ambiente di sviluppo integrato. Va notato che alcuni linguaggi di programmazione recenti consentono anche una forma mista di programmazione, in cui alla stesura di codice sorgente ASCII si associano anche operazioni di programmazione visuale, attraverso le quali il programmatore descrive alcuni aspetti del programma disegnando a video attraverso il mouse; un'applicazione tipica di quest'ultima forma di programmazione è il disegno interattivo della GUI del programma (finestre, menù, e così via).

Il codice sorgente, contenente le istruzioni da eseguire e (spesso) alcuni dati noti e costanti, può essere poi eseguito passandolo ad un interprete che eseguirà le istruzioni in esso contenute, il che è la prassi normale per i linguaggi di scripting; oppure può venire compilato, cioè tradotto in istruzioni di linguaggio macchina da un programma compilatore: il risultato è un file binario eseguibile che non ha bisogno di altri programmi per andare in esecuzione, ed è anche molto più veloce di un programma interpretato.

In passato, la compilazione è stata la norma per tutti i linguaggi di programmazione di uso generale; attualmente vi sono numerosi linguaggi interpretati e di uso generale, come il linguaggio Java o quelli della piattaforma .NET, che applicano un ibrido fra le due soluzioni, utilizzando un compilatore per produrre del codice in un linguaggio intermedio (detto bytecode) che viene successivamente interpretato. La differenza di prestazioni tra i linguaggi interpretati e quelli compilati è stata ridotta con tecniche di compilazione just-in-time, sebbene si continui ad utilizzare i linguaggi compilati (se non addirittura l'assembly) per le applicazioni che richiedono le massime prestazioni possibili.

La compilazione è il processo per cui il programma, scritto in un linguaggio di programmazione ad alto livello, viene tradotto in un codice eseguibile per mezzo di un altro programma detto appunto compilatore.

La compilazione offre numerosi vantaggi, primo fra tutti il fatto di ottenere eseguibili velocissimi adattando vari parametri di questa fase all'hardware a disposizione; ma ha lo svantaggio principale nel fatto che è necessario compilare un eseguibile diverso per ogni sistema operativo o hardware sul quale si desidera rendere disponibile l'esecuzione.

Se il programma, come spesso accade, usa delle librerie, o è composto da più moduli software, questi devono essere collegati tra loro. Lo strumento che effettua questa operazione è detto appunto linker ("collegatore"), e si occupa principalmente di risolvere le interconnessioni tra i diversi moduli.

Esistono principalmente due tipi differenti di collegamento: dinamico e statico.

Tutti i moduli del programma e le librerie utilizzate vengono incluse nell'eseguibile, che risulta grande, ma contiene tutto quanto necessario per la sua esecuzione. Se si rende necessaria una modifica ad una delle librerie, per correggere un errore o un problema di sicurezza, tutti i programmi che le usano con collegamento statico devono essere ricollegati con le nuove versioni delle librerie.

Le librerie utilizzate sono caricate dal sistema operativo quando necessario (linking dinamico; le librerie esterne sono chiamate "DLL", Dynamic-link libraries nei sistemi Microsoft Windows, mentre "SO" Shared Object nei sistemi Unix-like). L'eseguibile risultante è più compatto, ma dipende dalla presenza delle librerie utilizzate nel sistema operativo per poter essere eseguito.

In questo modo, le librerie possono essere aggiornate una sola volta a livello di sistema operativo, senza necessità di ricollegare i programmi. Diventa anche possibile usare diverse versioni della stessa libreria, o usare librerie personalizzate con caratteristiche specifiche per il particolare host.

Nella realizzazione di un progetto software complesso, può succedere che alcune parti del programma vengano realizzate come librerie, per comodità di manutenzione o per poterle usare in diversi programmi che fanno parte dello stesso progetto.

La complicazione aggiunta è che quando si installa un programma con collegamento dinamico è necessario verificare la presenza delle librerie che utilizza, ed eventualmente installare anche queste. I sistemi di package management, che si occupano di installare i programmi su un sistema operativo, di solito tengono traccia automaticamente di queste dipendenze.

In genere si preferisce il collegamento dinamico, in modo da creare programmi piccoli e in generale ridurre la memoria RAM occupata, assumendo che le librerie necessarie siano già presenti nel sistema, o talvolta distribuendole insieme al programma.

Per cercare di eliminare il problema della portabilità, si è tentato di creare altri linguaggi che si potessero basare soltanto su librerie compilate (componenti) ad hoc per ogni piattaforma, mentre il loro codice viene interpretato, e quindi non c'è la necessità di una compilazione su ogni tipologia di macchina su cui viene eseguito. Il grosso difetto di questi linguaggi è la lentezza dell'esecuzione; però hanno il grosso pregio di permettere di usare lo stesso programma senza modifica su più piattaforme. Si dice in questo caso che il programma è portabile.

La perdita di prestazioni che è alla base dei linguaggi interpretati è il doppio lavoro che è affidato alla macchina che si accinge ad elaborare tale programma. Al contrario di un programma compilato, infatti, ogni istruzione viene controllata e interpretata ad ogni esecuzione da un interprete.

Si usano linguaggi interpretati nella fase di messa a punto di un programma per evitare di effettuare numerose compilazioni o invece quando si vuole creare software che svolgono operazioni non critiche che non necessitano di ottimizzazioni riguardanti velocità o dimensioni, ma che traggono più vantaggio dalla portabilità. I linguaggi di scripting e tutti quelli orientati al Web sono quasi sempre interpretati. PHP, Perl, Tcl/Tk, Java volendo, e JavaScript, Python e molti altri sono esempi concreti di interazione non vincolata alla piattaforma.

Ci sono vari tentativi per rendere i compilatori multipiattaforma creando un livello intermedio, una sorta di semi-interpretazione, come nel caso sopra menzionato di Java; d'altro canto per i linguaggi interpretati ci sono tentativi per generare delle compilazioni (o semi-compilazioni) automatiche specifiche per la macchina su cui sono eseguiti.

Esistono anche strumenti per automatizzare per quanto possibile la compilazione di uno stesso programma su diverse piattaforme, ad esempio GNU autoconf/automake, che permette di realizzare una distribuzione del codice sorgente che può essere configurata e compilata automaticamente su diverse piattaforme, in genere almeno tutti gli Unix.

Questi due metodi di creazione ed esecuzione di un programma presentano entrambi vantaggi e svantaggi: il maggior vantaggio della compilazione è senz'altro l'efficienza nettamente superiore in termini di prestazioni, al prezzo del restare vincolati ad una piattaforma (combinazione di architettura hardware e sistema operativo) particolare; un linguaggio interpretato invece non ha, in linea di massima, questa dipendenza ma è più lento e richiede più memoria in fase di esecuzione.

Ad oggi (2007) esistono circa 2500 linguaggi di programmazione più o meno noti e diffusi: questi vengono normalmente classificati in tre grandi famiglie basate sul paradigmi di programmazione di riferimento: i linguaggi imperativi, quelli funzionali e quelli logici.

Nei linguaggi imperativi l'istruzione è un comando esplicito, che opera su una o più variabili oppure sullo stato interno della macchina, e le istruzioni vengono eseguite in un ordine prestabilito. Scrivere un programma in un linguaggio imperativo significa essenzialmente occuparsi di cosa la macchina deve fare per ottenere il risultato che si vuole, e il programmatore è impegnato nel mettere a punto gli algoritmi necessari a manipolare i dati.

Le strutture di controllo assumono la forma di istruzioni di flusso (GOTO, FOR, IF/THEN/ELSE ecc.) e il calcolo procede per iterazione piuttosto che per ricorsione. I valori delle variabili sono spesso assegnati a partire da costanti o da altre variabili (assegnamento) e raramente per passaggio di parametri (istanziazione).

La programmazione strutturata è una tecnica il cui scopo è di limitare la complessità della struttura del controllo dei programmi. Il programmatore è vincolato ad usare solo le strutture di controllo canoniche definite dal Teorema di Böhm-Jacopini, ovvero la sequenza, la selezione e il ciclo, evitando le istruzioni di salto incondizionato.

La programmazione a oggetti è basata su una evoluzione del concetto di tipo di dato astratto caratterizzata da incapsulamento, ereditarietà, polimorfismo. Oltre a linguaggi specializzati che implementano completamente i principi di tale metodologia (come Smalltalk o Java), molti linguaggi moderni incorporano alcuni concetti della programmazione a oggetti.

I linguaggi funzionali sono basati sul concetto matematico di funzione. In un linguaggio funzionale puro l'assegnazione esplicita risulta addirittura completamente assente (si utilizza soltanto il passaggio dei parametri). In tale modello rivestono particolare importanza la ricorsione, e, come struttura dati, la lista (sequenza ordinata di elementi). Il più importante rappresentante di questa categoria è senz'altro il Lisp (LISt Processing).

Nei linguaggi logici l'istruzione è una clausola che descrive una relazione fra i dati: programmare in un linguaggio logico significa descrivere l'insieme delle relazioni esistenti fra i dati e il risultato voluto, e il programmatore è impegnato nello stabilire in che modo i dati devono evolvere durante il calcolo. Non c'è un ordine prestabilito di esecuzione delle varie clausole, ma è compito dell'interprete trovare l'ordine giusto.

La struttura di controllo principale è rappresentata dal cut, che è detto rosso se modifica il comportamento del programma o verde se rende solo più efficiente il calcolo, che procede per ricorsione e non per iterazione. Le variabili ricevono il loro valore per istanziazione o da altre variabili già assegnate nella clausola (unificazione) e quasi mai per assegnamento, che è usato solo in caso di calcolo diretto di espressioni numeriche.

Affinché sia possibile usarli in un programma dichiarativo, tutti i normali algoritmi devono essere riformulati in termini ricorsivi e di backtracking; questo rende la programmazione con questi linguaggi una esperienza del tutto nuova e richiede di assumere un modo di pensare radicalmente diverso, perché più che calcolare un risultato si richiede di dimostrarne il valore esatto. A fronte di queste richieste, i linguaggi dichiarativi consentono di raggiungere risultati eccezionali quando si tratta di manipolare gruppi di enti in relazione fra loro.

I moderni supercomputer e - ormai - tutti i calcolatori di fascia alta e media sono equipaggiati con più CPU. Come ovvia conseguenza, questo richiede la capacità di sfruttarle; per questo sono stati sviluppati dapprima il multithreading, cioè la capacità di lanciare più parti dello stesso programma contemporaneamente su CPU diverse, e in seguito alcuni linguaggi studiati in modo tale da poter individuare da soli, in fase di compilazione, le parti di codice da lanciare in parallelo.

I linguaggi di questo tipo nacquero come linguaggi batch: vale a dire liste di comandi di programmi interattivi che invece di venire digitati uno ad uno su una linea di comando, potevano essere salvati in un file, che diventava così una specie di comando composto che si poteva eseguire in modalità batch per automatizzare compiti lunghi e ripetitivi. I primi linguaggi di scripting sono stati quelli delle shell Unix; successivamente, vista l'utilità del concetto molti altri programmi interattivi iniziarono a permettere il salvataggio e l'esecuzione di file contenenti liste di comandi, oppure il salvataggio di registrazioni di comandi visuali (le cosiddette Macro dei programmi di videoscrittura, per esempio).

Il passo successivo fu quello di far accettare a questi programmi anche dei comandi di salto condizionato e delle istruzioni di ciclo, regolati da simboli associati ad un certo valore: in pratica implementare cioè l'uso di variabili. Ormai molti programmi nati per tutt'altro scopo offrono agli utenti la possibilità di programmarli in modo autonomo tramite linguaggi di scripting più o meno proprietari. Molti di questi linguaggi hanno finito per adottare una sintassi molto simile a quella del C: altri invece, come il Perl e il Python, sono stati sviluppati ex novo allo scopo. Visto che nascono tutti come feature di altri programmi, tutti i linguaggi di scripting hanno in comune il fatto di essere Linguaggi interpretati, cioè eseguiti da un altro programma (il programma madre o un suo modulo).

Non ha senso, in generale, parlare di linguaggi migliori o peggiori, o di linguaggi migliori in assoluto: ogni linguaggio nasce per affrontare una classe di problemi più o meno ampia, in un certo modo e in un certo ambito. Però, dovendo dire se un dato linguaggio sia adatto o no per un certo uso, è necessario valutare le caratteristiche dei vari linguaggi.

Sono le qualità del linguaggio in sé, determinate dalla sua sintassi e dalla sua architettura interna. Influenzano direttamente il lavoro del programmatore, condizionandolo. Non dipendono né dagli strumenti usati (compilatore/interprete, IDE, linker) né dal sistema operativo o dal tipo di macchina.

A volte, un programma molto complesso e poco leggibile in un dato linguaggio può diventare assolutamente semplice e lineare se riscritto in un linguaggio di classe differente, più adatta.

L'esempio più comune di linguaggio robusto è il Pascal, che essendo nato a scopo didattico presuppone sempre che una irregolarità nel codice sia frutto di un errore del programmatore; mentre l'assembly è l'esempio per antonomasia di linguaggio totalmente libero, in cui niente vincola il programmatore (e se scrive codice pericoloso o errato, non c'è niente che lo avverta).

Oltre alle accennate qualità dei linguaggi, possono essere esaminate quelle degli ambienti in cui operano. Un programmatore lavora con strumenti software, la cui qualità e produttività dipende da un insieme di fattori che vanno pesati anch'essi in funzione del tipo di programmi che si intende scrivere.

Per la parte superiore



Programmazione (informatica)

Un insieme di testi di programmazione.

La programmazione è l'insieme delle attività che una persona, il programmatore, svolge per creare un programma, ossia un software. Un buon paragone è quello con l'insegnamento: è come se il programmatore "insegnasse" al computer come svolgere un determinato compito.

Il risultato delle attività di programmazione è il codice sorgente, tipicamente un testo scritto in un linguaggio di programmazione, il quale è ancora comprensibile al programmatore, ma è strutturato in maniera sufficientemente razionale da poter essere tradotto in maniera automatica in codice macchina tramite compilatori e interpreti. Questa fase è indispensabile ai fini dell'esecuzione del programma, poiché la CPU è in grado di eseguire solo codice macchina.

In alternativa alla classica programmazione testuale, possono esistere anche altre forme di programmazione come la programmazione grafica con i diagrammi Ladder. I programmi in Ladder, a seguito della compilazione, producono comunque codice macchina eseguibile da una CPU.

Il codice di un programma interpretato viene salvato cosi com'è, e viene poi letto da un interprete, che è un programma che gira sul sistema operativo in uso.

I linguaggi di programmazione compilati richiedono invece che il codice, una volta terminato, sia processato da un compilatore che, convertendolo in linguaggio macchina, ne permette l'esecuzione da parte della CPU.

I programmi interpretati sono più lenti ma più facili da creare e girano su molti sistemi operativi, a patto di avere lo stesso interprete, e che il dialetto del linguaggio sia comune. I linguaggi compilati, molto spesso, hanno invece degli standard ISO, o comunque regole universali, le quali permettono di compilare un programma senza modifiche su più architetture, anche da una sola macchina, a patto di avere un compilatore adeguato.

Java è pseudocompilato, ossia viene tradotto in un linguaggio intermedio, detto bytecode, il quale è una specie di linguaggio macchina, che viene poi passato all'inteprete, che deve essere disponibile per il tipo di macchina che si vuole utilizzare.

Il Visual Basic, per contro, non è un linguaggio standard, ma un ambiente di sviluppo creato per sviluppare programmi in un Basic ad oggetti sviluppato dalla Microsoft, e come tale disponibile solo sui loro OS. Non esistendo uno standard riconosciuto, non viene garantita la compatibilità tra versioni successive, e non è possibile utilizzarlo pienamente su altri sistemi operativi o altre CPU che quelle supportate dalla Microsoft.

La programmazione si è resa necessaria per l'avvenuta capacità tecnologica dell'uomo di creare macchine in grado di eseguire un algoritmo generico; sebbene infatti sia immaginabile programmare senza macchina e scrivere un programma (di solito in uno pseudolinguaggio) senza lo scopo di farlo girare, l'accezione comune del termine programmazione è proprio quella di impartire istruzioni a una macchina ragionevolmente complessa che sia in grado di seguire le istruzioni stesse.

Esistono molte altre tecniche, che sarebbe più opportuno però definire paradigmi di programmazione. Vedere la voce stessa per approfondimenti.

Gli errori di programmazione si possono distinguere in tre categorie: errori di logica, errori di sintassi ed errori di runtime.

Per la parte superiore



Source : Wikipedia