Breve introduzione a NewLisp.

29 01 2008

Introduzione

NewLisp e` un linguaggio di programmazione funzionale… ma cosa e` esattamente un linguaggio funzionale? Partiamo dalla definizione data da Wikipedia:

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.

Prendiamo anche quest’altra definizione:

Si dice che una funzione produce un effetto collaterale quando modifica un valore o uno stato al di fuori del proprio scoping locale. Per esempio, una funzione ha un effetto collaterale quando modifica una variabile globale o statica, quando modifica uno dei suoi argomenti[1], quando scrive dati su di un display o su di un file o quando invoca altre funzioni con effetti collaterali.
Gli effetti collaterali presenti in un programma spesso rendono difficile la comprensione del suo flusso di esecuzione e se non gestiti bene possono portare facilmente a bug difficili da scovare.

NewLisp non e` un linguaggio funzionale puro, nel senso che permette di fare delle cose che in un linguaggio funzionale “puro” non si dovrebbero poter fare. Anche se questo puo` far storcere il naso a qualcuno, io credo che sia in realta` un punto vincente di NewLisp, in quanto alcuni vincoli imposti dai linguaggi funzionali puri potrebbero non adattarsi al meglio ad un linguaggio di scripting come questo.

(un’altra interessante definizione sui linguaggi funzionali la potete trovare qui: http://programmazione.it/index.php?entity=eitem&idItem=30406)

Installare NewLisp

NewLisp puo` essere scaricato dal sito seguente (area download):

http://newlisp.org/index.cgi?page=Downloads

Ci sono le versioni per Windows, per Linux, per Mac OSX. Inoltre, trovate la release stabile e quella attualmente in sviluppo (che, comunque, e` sufficientemente stabile per poterci lavorare).
Si hanno a disposizione tre ambienti di sviluppo, uno in console, uno in Tk, e l’altro in Java.

Diamo una prima occhiata al linguaggio!

Alcune caratteristiche di NewLisp hanno sono di forte impatto per chi viene dai linguaggi imperativi (come il C, PHP, Pascal, Java, C#, Visual Basic, etc…). Uno di questi e` che, in NewLisp, ogni cosa e` un simbolo. Cosa significa? Nei linguaggi imperativi esiste una netta differenza tra dati e programma, mentre NewLisp tratta tutte le informazioni genericamente come “simboli”.
Analizziamo l’espressione seguente:

> (+ 7 5)
12

E` una espressione scritta in NewLisp. Il Lisp (e suoi derivati) e` “rinomato” per l’uso smodato delle parentesi. Vedremo pero` in seguito che, questo apparente problema, e` in realta` una feature notevole. Nel nostro caso la funzione “+” permette di sommare un numero indeterminato di elementi, compresi nelle parentesi. Possiamo quindi scrivere:

 > (+ 1 2 3 4 5 6 7 8 9 10)
55

Qui gia` abbiamo un “assaggio” del vantaggio dell’uso delle parentesi. Il loro utilizzo ci permette di delimitare il range di azione di una funzione. In un linguaggio imperativo, la precedente funzione potrebbe essere scritta come:

]>> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10

Oppure:

]>> sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

Il “+” e` un simbolo, ed in base al suo uso noi chiederemo a NewLisp di valutare l’espressione “+” o no. Potremmo infatti scrivere:

> (set 'res (+ 7 5) )
12
> (set 'res '(+ 7 5) )
(+ 7 5)

Notate la differenza: nel primo caso abbiamo chiesto di calcolare la somma dei valori 7 e 5 e di assegnare il risultato (con set) alla variabile res. NewLisp ci mostra “12″. Nel secondo caso abbiamo chiesto a NewLisp di assegnare alla variabile res la lista (+ 7 5) (notate il piccolo apice ” ” davanti alla parentesi aperta della lista: ” (+ 7 5) “). NewLisp non si scompone: o valuta un simbolo e le espressioni (e ci fornisce come risultato 12) oppure non lo valuta.
Le parentesi denotano un elemento fondamentale in NewLisp: le liste. Tutti i simboli sono contenuti in liste (non a caso il termine Lisp proviene da List Processor), e noi dobbiamo solamente dire a NewLisp quando valutare una lista (set ‘res (+ 7 5) ) e quando non farlo (set ‘res ‘(+ 7 5) ).

Il tutto e` molto semplice.

Prima di concludere questa breve introduzione, vorrei sottolineare un altro elemento fondamentale: NewLisp, essendo un linguaggio funzionale, usa esclusivamente espressioni, in ogni luogo, al contrario dei linguaggi imperativi che possono usare le espressioni solo nella parte destra di una assegnazione.
Per chiarire il concetto, vediamo l’esempio seguente:

> (set 'res (+ 7 5) )
12
]>> res = 7 + 5
12

In NewLisp abbiamo usato due espressioni annidate: “(set” e “(+”. Non esiste il concetto di left-side e right-side. Nel secondo esempio (scritto in un generico linguaggio imperativo), la parte sinistra denota la variabile, mentre la parte destra include una espressione.
Questa differenza, apparentemente irrilevante, permette invece di creare programmi molto espressivi e potenti.
Prendiamo, per esempio, la funzione map di NewLisp:

> (map println '("Hello" "World"))
Hello
World

Quello che abbiamo fatto e` mappare una funzione su una lista! La funzione println (stampa qualcosa) e` stata “mappata” sulla lista seguente (la quale non e` stata valutata perche` preceduta dall’apice singolo ” “). L’esempio e` gia` notevole, ma proviamo ad estenderlo un po`:

(set 'counter 1)

(map
    (fn (i)
        (println "Elemento " counter ": " i)
        (inc 'counter)
    );fn

    '(-3 -2 -1 0 1 2 3)
);map

Eseguendolo, otteniamo:

Elemento 1: -3
Elemento 2: -2
Elemento 3: -1
Elemento 4: 0
Elemento 5: 1
Elemento 6: 2
Elemento 7: 3

Il programma e` molto semplice (ho dato una sistemata alle parentesi per renderlo comprensibile al massimo, dandogli una forma tipicamente usata nei linguaggi imperativi).

Nella prima riga assegnamo il valore 1 alla variabile counter.
Poi usiamo la funzione map applicando una funzione-lambda (vedremo nel prossimo tutorial di cosa si tratta; in breve diciamo che e` una funzione senza un nome…) alla sequenza di numeri (-3 -2 -1 0 1 2 3).

Mappare una funzione con un’altra funzione e` solo la punta dell’iceberg (soprattutto se la funzione mappata non ha nome!): ci sono altri sistemi di mappatura creati ad-hoc; voi stessi potrete realizzare funzioni native (al pari di una funzione NewLisp!) che implementano questo metodo.

Tutto cio` e` possibile grazie a cio` che abbiamo detto poco fa` riguardo le espressioni e il left-side e right-side.

Nella prossima puntata inizieremo ad approfondire questi concetti, scoprendo le potenzialita` di questo bellissimo linguaggio.

A presto!


Azioni

Informazione

2 risposte

30 01 2008
newlisper

Magnifico! The English translation is not yet working – but I just love the new blog in Italiano…. :)

ciao

1 01 2009
darkini

Sempre il migliore!! grazie di tutto

Lascia un commento