Posts

April 23, 2011

Implementare i while senza usare keywords

Da una discussione con Antonio su come implementare il concetto di ciclo while nel tool di programmazione a oggetti su cui stiamo lavorando, è risultato che non serve creare costrutti sintattici particolari, ma basta un utilizzo oculato dei blocchi.

Come sempre, l’ispirazione arriva da Smalltalk.

Un esempio tipico di ciclo while è rappresentato dal fattoriale. Vediamone il calcolo per il numero 5, in Ruby:

 count = 5
 fattoriale = 1

 while count > 0 do
     fattoriale = fattoriale * count
     count -= 1
 end

 puts fattoriale

Il while valuta l’espressione passata (count > 0) ed esegue il blocco passato fintanto che tale espressione è vera.

Come per gli if, però, sarebbe stato possibile evitare di usare costrutti procedurali: è sufficiente aggiungere un messaggio while_true alla classe che rappresenta il blocco (cioè Proc), e usarlo in modo del tutto analogo al while:

 proc { count > 0 }.while_true do
     fattoriale = fattoriale * count
     count -= 1
 end

Il blocco anonimo { count > 0 } è un oggetto che risponde al messaggio while_true.

L’implementazione di while_true deve essere tale per cui, fintanto che l’esecuzione del blocco restituisce true, viene eseguito il blocco passato come parametro:

 class Proc
     def while_true &block
         self.call.if_true do
             block.call
             self.while_true &block
         end
     end
 end

while_true viene invocato ricorsivamente finché l’espressione del blocco che riceve il messaggio non è falsa.

(Per l’implementazione di if_true, si veda il post sugli if).

Può dare l’impressione di essere una banale modifica sintattica, ma si tratta di una differenza più sostanziale di quanto sembri.

Gestire i while in questo modo permette di rimuovere una parola chiave, semplificare il linguaggio, e renderlo più object oriented, dato che anche il ciclo while si riduce a uno scambio di messaggi.