Scrivere funzioni newLisp auto-commentate

11 07 2009

google_translate.gif Translate To English!

Introduzione

Una cosa che mi piacque molto quando studiai per la prima volta Rebol (un bellissimo linguaggio di programmazione funzionale, creato da Carl Sassenrath), è che si potevano inserire dei commenti all’interno delle funzioni stesse. Cercherò di essere un pò più chiaro. Normalmente, se scrivo un programma in Java (ma anche in C, Pascal, Basic, etc…) scrivo i commenti alle funzioni in un modo simile al seguente:

/* Questo è il commento alla mia  bellissima funzione */
function miaFunzione() {
   faccioQualcosa();
}

Il commento (quello in mezzo ai simboli /*  */ ), anche se posto sopra alla funzione stessa, è però staccato, indipendente da essa, sotto ogni punto di vista. Solo utilizzando programmi esterni (come javadoc) si può allora generare della documentazione che “colleghi” il commento alla funzione. Inoltre, se spostassi la funzione, o la mettessi in un altro programma, potrei anche dimenticare di copiare il suo commento. Nei linguaggi funzionali come newLisp e Rebol, possiamo però sfruttare la loro omoiconicità per inserire il commento all’interno della funzione stessa. Questo ci porterà notevoli vantaggi:

  1. Se copio / sposto la funzione, il commento verrà copiato con essa, sempre.
  2. Molti linguaggi di scripting (compreso newLisp) hanno una comoda console per impartire i comandi. Questo significa che, si possono realizzare dei comandi ad-hoc, per leggere tali commenti, direttamente dalla funzione stessa, e senza ricorrere a programmi esterni (simili a javadoc).
  3. Il commento (e la documentazione in genere), non essendo necessario estrarlo con tools esterni, sarà sempre aggiornato (non rischio di avere una funzione X ma con un commento estratto Y – più vecchio della funzione stessa, solo perchè non ho rilanciato il comando di aggiornamento della documentazione).
Passiamo alla pratica

Ora che ho chiarito (spero!) un pò meglio la mia idea, cerchiamo di capire come metterlo in pratica usando il nostro newLisp. Prima di tutto scriviamo una funzione molto semplice:

(define (somma-valori argValore1 argValore2)
   (println (+ argValore1 argValore2) )
)
>> (somma-valori 10 20)
30

Bene, ora che ho la funzione, inseriamo un breve commento per spiegare il suo funzionamento. Lo possiamo fare in diversi modi, in base al numero di informazioni (e al tipo) da mettere. Il sistema più semplice è inserire una stringa che contenga il commento (ma newLisp ci permetterà di fare ben altro!):

(define (somma-valori argValore1 argValore2)
   "Questa funzione addiziona due numeri interi."
   (println (+ argValore1 argValore2) )
)

La possibilità unica nel suo genere che hanno i linguaggi omoiconici è che il codice (il programma vero e proprio) e i dati sono in realtà la stessa cosa, quindi newLisp non si “scandalizza” se, nel bel mezzo di un programma, inseriamo una stringa, senza chiamare funzioni, senza assegnazioni! Ma ora arriva la parte più interessante: proprio perchè in newLisp i dati sono codice, ed il codice sono dati, possiamo manipolare la nostra funzione come una lista qualunque, quindi:

>> (nth 1 somma-valori)
"Questa funzione addiziona due numeri interi."

Meraviglioso! Abbiamo potuto estrarre il commento dalla funzione! Ora guardate qui… create nel vostro ambiente newLisp (dalla console) questa funzione:

(define (helpme argFunction)
   (nth 1 argFunction)
)

Ora provate a digitare:

>> (helpme somma-valori)
"Questa funzione addiziona due numeri interi."

Fantastico! Basta quindi stabilire uno standard ed avremo, gratis (  :-)  ) , un comodo sistema di help online! Ma allora, perchè fermarci qui? Proviamo in questo modo:

(define (somma-valori argValore1 argValore2)
   (
      (comment "Questa funzione addiziona due numeri interi.")
      (version 1.1)
      (last-update "2009-07-01")
   )
   (println (+ argValore1 argValore2) )
)

Il nostro semplice commento, scritto sottoforma di stringa, ora è diventato una lista, contenente dei “tag” (comment / version / last-update) rileggibili dalla nostra funzione di help:

(define (helpme argFunction)
   ( println "DESCRIPTION: " (lookup 'comment (nth 1 argFunction)) )
   ( println "VERSION    : " (lookup 'version (nth 1 argFunction)) )
   ( println "LAST-UPDATE: " (lookup 'last-update (nth 1 argFunction)) "\n" )
)

>> (helpme somma-valori)
DESCRIPTION: Questa funzione addiziona due numeri interi.
VERSION    : 1.1
LAST-UPDATE: 2009-07-01

I vantaggi di un metodo simile sono evidenti: se aggiungessimo anche una funzione per indicizzare le funzioni scritte (quindi potendo anche cercarle scrivendo solo una parte del loro nome), allora avremo un ambiente di sviluppo e test di prim’ordine!

Anche stavolta siamo quasi alla fine. Spero che l’articolo possa fornirvi spunti utili al vostro lavoro e divertimento!

A presto!





CrunchBang linux, *newLisp*, zenity, lighttpd, dmenu, Opera & Netbooks!

25 06 2009

google_translate.gif Translate To English!

Eccomi di nuovo qui con un articolo in parte off-topic (ma non troppo!). Questa volta però ho deciso di confondervi le idee, immettendo un titolo a questo articolo decisamente strano.
Insomma, di cosa parliamo stavolta? Si parlerà della moda del momento: i netbooks! Si tratta di moda o vera necessità? Dovè la verità? Il tempo ce lo dirà (oltre che programmatore sono diventato anche poeta! Guarda che rima che ho fatto!).

Al di là delle questioni “filosofiche”, è un dato di fatto che i netbooks stanno riscuotendo un enorme successo. Purtroppo però sembra che, come troppo spesso accade, una bella idea (vera innovazione o evoluzione?) venga un poco rovinata da ciò che la circonda. Piccoli gioielli come questi si meriterebbero anche dei sistemi operativi adeguati, ma nonostante sia passato un pò di tempo, siamo ancora in alto mare (ok, ok, ci sono molte distribuzioni linux, ma a mio parere siamo ancora lontani da quello che dovrebbe essere il vero sistema operativo per sfruttare appieno questi piccoli computers). Al di là poi della “potenza” del netbook stesso, anche le interfacce dovrebbero cambiare radicalmente. Certo che diverse distribuzioni linux hanno fatto molti passi in avanti, però ho l’impressione che l’obiettivo finale (a lungo termine) non verrà centrato (la direzione in cui si sta andando sembra giusta però, a mio parere, manca ancora qualcosa… forse con Moblin 2 – creato come O.S. più simile a quello di un cellulare che ad un O.S. tradizionale – cambierà qualcosa, ma ci sono ancora troppe applicazioni “standard”).

Va bene, non sono però qui a scrivere per parlare della validità di questo programma o di quell’altro sistema operativo, ma vorrei invece darvi un suggerimento, da veri smanettoni, per creare una distribuzione linux veramente adatta alle vostre esigenze.
Ho da poco provato la distribuzione linux CrunchBang Linux e, anche se un pò “scarna” per un profano, credo sia un autentico gioiello se messa nelle mani di uno smanettone. Si configura con pochi files di testo (xml), ha dei tools semplici ma efficaci, è molto leggera (sul mio netbook Acer Aspire One A110 occupa meno di 100Mb di RAM quando è in funzione), ed è VELOCE (deriva da Ubuntu 8.10).

newLisp funziona magnificamente.

Se vi serve un web server vi consiglio lighttpd. E’ veloce (parte in un baleno), si configura con un file di testo, supporta le CGI (pure quelle fatte in newLisp), ed occupa pochissima memoria.

Se volete realizzare degli script di configurazione/personalizzazione della distro, potete usare zenity e dmenu . Il primo è un programma che, lanciato a linea comando, permette di generare delle forms grafiche (vedi il mio precedente articolo: http://newlisp.wordpress.com/2009/05/01/usare-newlisp-nella-shell-di-linux/ ). Mentre il secondo è un meraviglioso programma in grado di generare un menu a partire da un input generico, prendere la selezione dell’utente (item scelto tra quelli proposti nel menu) e ritornarlo alla linea comando. Può gestire ricerche tra le voci proposte, ed lavora agevolmente con migliaia di items (esempio: digitate ls -l | dmenu ed avrete già pronto un menu di selezione di un file). Questi due software sono favolosi se accoppiati a newLisp!

Riguardo Opera, ne ho già parlato in passato, e la versione 10beta è ottima sul netbook: occupa meno risorse di FireFox, ha una valanga di funzionalità, ed è ACID-3 compliant. Contiene pure molti widgets (anche se non tanti come il mitico FireFox ).

Questi tools li sto usando sul mio “piccolino”, ed il tutto funziona a meraviglia.

Anche per oggi è tutto, se volete delucidazioni o approfondimenti, non avete che da chiedere! Io sono qui a vostra disposizione!

A presto!!!





Usare newLisp come shell-scripting

10 06 2009

google_translate.gif Translate To English!

Vorrei sottoporvi un interessante, piccolo/grande modo di risolvere i problemi di tutti i giorni.

No, non useremo newLisp per evitare che i toast la mattina non si brucino :-)   ma vedremo un altro esempio su come usare newLisp per sostituire efficacemente lo scripting shell (tipicamente bash, zsh, csh, etc… per Linux/Un*x).

Un paio di giorni fà mi sono ritrovato con un piccolo/grande problema: avevo moltissimi files C divisi in diverse sottodirectories, e dovevo cercarne alcuni che contenessero una determinata funzione.
Mi sono affidato quindi al buon vecchio cat unito al grep, nel modo seguente:

cat *.c | grep miaFunzione

Purtroppo questo sistema funziona se non devo fare ricerche anche nelle sottodirectories.
Ho quindi cercato soluzioni alternative. Ne ho trovate alcune, ma non sempre mi hanno funzionato (delle volte è difficile trovare qualcosa su internet se non si sà bene che chiavi di ricerca usare!).
Allora ho pensato di realizzare ciò che mi serviva usando newLisp! La domanda era però: posso fare in newLisp uno script abbastanza breve da poter essere usato come valida alternativa alla bash e ai suoi potentissimi comandi (comprese le pipes, redirezioni, etc…)?
Bè, dopo alcuni minuti di riflessione la risposta è stata… SI! Ed ecco cosa è uscito fuori:

(dolist (i (exec "ls *.c")) (println (exec (string "cat -n " i " | grep miaFunzione") ) ) )

Lo script è comunque molto corto, sfrutta le potenzialità dei comandi ls, grep e cat ma ho usato newLisp come collante tra loro.
Si può anche usare l’elegante e potente funzione map e le lamba functions come segue:

(map (fn (i) (exec (string "cat -n " i " | grep miaFunzione") ) ) (exec "ls *.c") )

La lunghezza dello script è simile al precedente, ma in questo modo non si effettuano cicli (dolist). Inoltre la funzione lambda può essere tranquillamente sostituita con altre funzioni che operano su liste di files… e qui solo la fantasia è il vero limite!

Ora spieghiamo velocemente i due script. Partiamo dal primo.
Prima di tutto scriviamolo in una forma più leggibile:

(dolist (i (exec "ls *.c") )
   (println
      (exec (string "cat -n " i " | grep miaFunzione") )
   )
)

La funzione exec esegue un programma esterno all’interprete newLisp (in questo caso esegue ls *.c), e ritorna il risultato come lista di dati. Ecco un esempio:

> (exec "ls *.lsp")
("demo.lsp" "editor.lsp")

Con la funzione dolist scorro la lista così ottenuta, e compongo il secondo comando, usando cat (stampa i contenuti di un file di testo) e grep (ricerca una stringa all’interno del testo emesso da cat).

Nel secondo esempio – usando la funzione map – invece ho creato una lambda function, la quale riceve la lista di file, uno ad uno, grazie alla funzione map.

L’esempio con la map credo sia più elegante ed infinitamente più flessibile. Per esempio potrei crearmi delle funzioni che effettuino filtri o operazioni particolari su gruppi di files. Allo scopo potrei costruirmi due set di funzioni: una che legge i dati in un determinato modo, mentre il secondo blocco potrebbe effettuare le più disparate operazioni su di essi.

Vedremo in futuro un’applicazione pratica di tutto ciò. Per ora… arrivederci!