Proposta per un incontro!

22 05 2009

google_translate.gif Translate To English!

Questa volta non sto scrivendo per fornire un’altra idea sull’argomento, ma per dirvi che sono rimasto piacevolmente colpito da quante persone hanno risposto/commentato questi miei “originali” articoli.

A fronte di tutto ciò vorrei lanciare una proposta: vediamoci da qualche parte, un giorno, e scambiamo due chiacchiere di persona. Sono sicuro che potremo passare una piacevole giornata, parlando dell’argomento, proponendo nuove letture, spunti per altre riflessioni, etc…

Un pò di tempo fà ho parlato con il responsabile di una bellissima libreria che si trova a Rieti, e loro non escludono l’idea di ospitare un incontro simile. Potremmo anche fondare un vero club, ed organizzare riunioni annuali!

Che ne pensate?

Aspetto con ansia un vostro feedback!





I context e la loro serializzazione

19 05 2009

google_translate.gif

Translate To English!

Buon giorno a tutti! Siamo oggi qui riuniti per svelare una potente e forse poco conosciuta funzionalità dei context: la possibilità di serializzare il loro stato, così da essere salvato e ripristinato in seguito, oppure per essere inviato ad un nodo di un altra macchina, etc… L’articolo è relativamente breve ma dal forte impatto, al termine del quale il mondo attorno a voi non sarà più lo stesso! Si inizia!

Partiamo subito con un pò di codice:

(define (foo:foo)
    (inc foo:conta) )
> (foo)
1
> (foo)
2
> (foo)
3
> foo:conta
3

Abbiamo appena creato un nuovo contesto, chiamato foo, con una funzione associata che incrementa una variabile, di nome conta, che viene incrementata di uno ogni volta che si richiama il contesto stesso (ogni contesto ha un functor, cioè una funzione di default che viene eseguita non appena viene richiamato il contesto stesso). Nulla di sconvolgente (tranne il functor, che è decisamente interessante!).

Come potete notare dall’ultima istruzione, il valore di conta in foo vale 3.

Ora…

> (save "foo.lsp" 'foo)
true

Ho appena salvato il contesto. E qui avviene la “magia”: salvando il contesto ho salvato anche il suo stato… quindi…  :-)

Chiudete la sessione newLisp in cui avete lavorato, ed apritene un’altra, poi digitate:

> (load "foo.lsp")
MAIN

> foo:conta
3

Cosa?! Si lo so, non credete ai vostri occhi! Lo stato appena salvato lo abbiamo ricaricato, ed è li!!! Con una sola funzione. Fantastico.
(quanti linguaggi serializzano i dati con tanta facilità?)

Ora immaginate i campi applicativi: persistenza dei dati nei server web, invio di interi contesti tra nodi di macchine distribuite su rete, distribuzione del carico spostando i processi in esecuzione (spostando anche i dati, così da non perdere nemmeno un bit delle sessioni attive!), etc…

Non aggiungo altro.

Alla prossima!!!





Funzione non ricorsiva e senza loop che viene eseguita indefinitivamente!

4 05 2009

google_translate.gif Translate To English!

Stavo dando una occhiata al blog di Kazimir (http://kazimirmajorinc.blogspot.com/), uno dei miei blog preferiti per newLisp.
E’ veramente bravo, e delle volte pubblica degli articoli che mi fanno impazzire (belli, originali, semplici e geniali!).

Uno di questi è intitolato… Crawler Tractor. …

Cosa? Come dite? Cosa c’entra questo con newLisp… ora ve lo spiego…

newLisp delle volte permette di fare delle cose veramente curiose, e questa è una! Nell’esempio è stata realizzata una funzione NON ricorsiva e senza loop, ma in grado di funzionare e produrre risultati indefinitivamente. Il codice è semplicissimo (pubblico quello mostrato da Kazimir), poi vi spiegherò come funziona (anche se il programma è molo piccolo da esso si possono trarre spunti e suggerimenti molto interessanti!):

(set 'f 
 (lambda()
   (begin
     (println "Hi for the " (inc counter) ". time. ")
     (push (last f) f -1)
     (if (> (length f) 3) (pop f 1) ) ) ) )
(f)

Il programma produrrà un risultato simile al seguente:

; Hi for the 1. time.
; Hi for the 2. time.
; Hi for the 3. time.
; Hi for the 4. time.
; Hi for the 5. time.
; Hi for the 6. time.
......... e così via ........

Come è possibile tutto ciò?

Analizziamo un paio di righe di codice che compiono la “magia”:

(push (last f) f -1)

La funzione (last f) ritorna il corpo della funzione stessa, cioè tutto ciò che si trova all’interno del (begin), begin compreso:

(begin
     (println "Hi for the " (inc counter) ". time. ")
     (push (last f) f -1)
     (if (> (length f) 3) (pop f 1) ) ) ) )

Quindi, la funzione (push) non fà altro che inserire il corpo del programma dentro sè stessa. Questo è possibile grazie al dualismo codice<->dati che ha newLisp. Vi faccio un esempio più semplice:

> ( set 'f (fn () (println "ok") ) )
(lambda () (println "ok"))
> (push (last f) f -1)
(lambda () (println "ok") (println "ok"))

Come potete vedere, la funzione (push) appende alla funzione corrente, in esecuzione, un nuovo pezzo di codice, cioè il corpo della funzione stessa! GENIALE!

L’ultima riga (quella con la IF) serve per eliminare il codice “vecchio”, già eseguito e completato. NOTA: viene usato come termine di confronto il valore > 3 , questo per evitare di eliminare il pezzo di codice attualmente in esecuzione!

Sto quindi facendo qualcosa simile a ciò che “secoli” fà (scusate ma io sono “vecchietto”) si faceva in linguaggio macchina: si generava codice auto-generante. Infatti questa tecnica potrebbe essere utilizzata non sono per replicare n-volte codice esistente (come nel nostro caso), ma anche per generare/modificare al volo codice esistente.

Questo articolo mi ha fatto venire in mente anche ciò che si fà in Erlang, chiamando una funzione ricorsiva come ultima chiamata, la quale permette di implementare la ricorsività senza però andare ad intaccare lo stack  (evitando spiacevoli stack-overflow)   :-)

Come dite? Al termine di questo mini-articolo non avete comunque capito che cosa c’entra il trattore? Ditemelo voi… (o chiedetelo a Kazimir!).

A presto!