Sei sulla pagina 1di 33

In questa guida tratteremo del linguaggio

Ruby, che dopo un decennio di diffusione


solo tra gli appassionati si sta
affacciando, con grande merito, sulla
scena mainstream. Che il 2006 sia stato
lanno di Ruby non c dubbio alcuno
abbiamo assistito allafferma!ione dei
frame"or# Ruby on Rails e $itro, sono
state pubblicate decine di %olumi sui %ari
aspetti del linguaggio, dal celebre
Coo#boo# alla raccolta dei migliori
Ruby&ui!, e le mailing list e i forum ad
esso dedicati straripano di iscritti.
Inoltre, dal mese di 'ennaio, Ruby compare nei primi dieci posti della classifica dei linguaggi pi(
popolari stilata mensilmente dalla )I*+,. - sicuramente un grandissimo risultato se si pensa che
stato progettato nel .//0 da un language designer non professionista, il giapponese 1u#ihiro 23at!4
3atsumoto, e che quindi non ha a%uto grosse realt5, commerciali o accademiche, pronte a
sostenerlo. *ggi le cose fortunatamente %anno di%ersamente, Ruby pu6 contare numerose 2success
stories4 alla $787, alla 3otorola e alla 9ucent solo per citarne alcune.
*ltre ai gi5 citati Rails e $itro, spiccano tra le applica!ioni scritte in Ruby il :i#i Insti#i, il blog
engine )ypo e le;ploitation frame"or# 3etasploit. <orrei porre latten!ione proprio su
questultimo, che dalla %ersione 0 stato riscritto completamente in Ruby, non tanto per
limportan!a che ri%este il progetto ma essen!ialmente per le moti%a!ioni che hanno portato a
questa scelta. Come si legge dalla documenta!ione stato scelto Ruby perch=>
1. 'li s%iluppatori di 3etasploit amano programmare in questo linguaggio. &uesta pu6
sembrare un argomento molto soggetti%o ma in realt5 racchiude una grande %erit5> Ruby fa
riscoprire la gioia di programmare. Inoltre gli aspetti ** cos? come gestiti da Ruby ben si
adattano ai requisiti di un frame"or# del genere
2. @a il supporto per il threading platformAindependent
0. 7 differen!a del Berl ha un interprete nati%o per piattaforme :indo"s, che si traduce in
presta!ione note%olmente migliori delle possibili alternati%e Cla %ersione Cyg"in e
7cti%e8tate del BerlD.
*ltre ad essere appre!!ato dai programmatori professionisti che ne utili!!ano le feature pi(
a%an!ate, il Ruby ben si presta anche ad essere imparato come primo linguaggio. *%%ero quel
linguaggio che permette, per la sua semplicit5, di passare dalla teoria dei libri alla pratica del
terminale sen!a grossi traumi, sen!a do%ersi preoccupare di innumere%oli con%en!ioni e aspetti non
strettamente legati alla programma!ione in s=. 7 tale proposito non si pu6 non citare il mera%iglioso
libro 9earn )o Brogram di Chris Bine disponibile sia liberamente online sia in %ersione estesa in
%ersione cartacea.
Eino a qualche tempo fa i detrattori sconsiglia%ano di utili!!are Ruby per la mancan!a di
documenta!ione Cin lingue di%erse dal giapponeseD, per la mancan!a di librerie e per la scarsa base
di programmatori esperti. )ali obie!ioni sono cadute una dopo laltra. *ggi abbiamo numerosi libri,
e siti, in inglese e ultimamente anche in italiano le librerie e le applica!ioni non mancano, basta
dare uno sguardo a RubyEorge e al Ruby 7pplication 7rchi%e CR77D e infine sul numero e sulla
qualit5 degli s%iluppatori Ruby non credo ci sia pi( nessun dubbio.
Caratteristiche di Ruby
Fiamo ora uno sguardo alle caratteristiche principali del Ruby. $iente paura, solo due parole in
modo da accontentare i fanatici del B9) e non annoiare tutti gli altri. Ruby un linguaggio open
source, general purpose e interpretato. - un linguaggio orientato agli oggetti puro nel senso che,
come nello 8malltal#, ogni cosa un oggetto con i propri metodi. Bresenta per6 anche aspetti del
paradigma imperati%o e di quello fun!ionale.
Ruby di per s= non ha niente di estremamente nuo%o ma prende il meglio dai pi( ri%olu!ionari
linguaggi, primi su tutti lo 8malltal# e il Berl, ma anche Byhton, 9I8B e Fylan. Il risultato
estremamente potente e sintatticamente grade%ole, infatti uno dei primi slogan del Ruby fu> Ruby >
(Smalltalk + Perl) / 2
)ra le altre caratteristiche che incontreremo, e approfondiremo, nel corso della guida %a ricordato il
duc# typing, i blocchi, gli iteratori e le chiusure e tante altre feature che rendono il linguaggio Ruby
unico.
Come si e%ince dallintrodu!ione Ruby stato progettato per essere semplice e immediato, per
questo moti%o segue il principio di minima sorpresa CPrinciple of least surprise, B*98D, o%%ero il
linguaggio si comporta cos? come il programmatore si aspetta, in maniera coerente e sen!a
impre%isti.
Ruby possiede inoltre una sintassi pulita e lineare che permette ai nuo%i s%iluppatori di imparare il
linguaggio, ed essere produtti%i, in pochissimo tempo. - possibile infine estendere Ruby in C e in
CGG in modo estremamente semplice se confrontato con i meccanismi di estensione degli altri
linguaggi.
n genere tutto quello che ser%e per scri%ere un programma un qualsiasi editor di testo e
o%%iamente un interprete. Ruby %iene distribuito insieme ad una serie di utility che %anno a creare
un ambiente di s%iluppo completo e flessibile.
*ltre allinterprete infatti tro%iamo una shell interatti%a, degli strumenti per la crea!ione e la
%isuali!!a!ione della documenta!ione, e infine strumenti per il testing e per le applica!ioni "eb.
<ediamo una %eloce carrellata degli 2attre!!i4 che utili!!eremo durante lo s%olgimento della guida.
Linterprete Ruby
Innan!itutto c linterprete Ruby che o%%iamente si occupa dellesecu!ione dei programmi. &ueste
sono le principali op!ioni, %isuali!!abili attra%erso lop!ione -help.
$ ruby --help
Usage: ruby [switches] [--] [programfile] [arguments]
-0[octal] specify record separator (, if no argument)
-a autosplit mode with -n or -p (splits $ into $!)
-c chec" synta# only
-$directory cd to directory, before e#ecuting your script
-d set debugging flags (set $%&'U( to true)
-e )command) one line of script* +e,eral -e)s allowed* -mit [programfile]
-!pattern split() pattern for autosplit (-a)
-i[e#tension] edit ./(0 files in place (ma"e bac"up if e#tension supplied)
-1directory specify $2-.%3.45 directory (may be used more than once)
-6"code specifies 6.781 (8apanese) code-set
-l enable line ending processing
-n assume )while gets()9 *** end) loop around your script
-p assume loop li"e -n but print line also li"e sed
-rlibrary re:uire the library, before e#ecuting your script
-s enable some switch parsing for switches after script name
-+ loo" for the script using 3.45 en,ironment ,ariable
-4[le,el] turn on tainting chec"s
-, print ,ersion number, then turn on ,erbose mode
-w turn warnings on for your script
-;[le,el] set warning le,el9 0<silence, =<medium, ><,erbose (default)
-#[directory] strip off te#t before ?@ruby line and perhaps cd to directory
--copyright print the copyright
--,ersion print the ,ersion
<ediamone in dettaglio alcune tra quelle che ci possono tornare utili in fase di apprendimento del
linguaggio>
-c> %iene controllata la sintassi dello script, che per6 non %iene eseguito. In caso di successo
%iene fuori un rassicurante 28ynta; *H4.
-d, --debug> da utili!!are in fase di debug, la %ariabile IF,+J' impostata a 2true4.
-,, --,erbose> mostra informa!ioni addi!ionali in output C%ersione dellinterprete,
"arning in fase di compila!ione, etc.D.
-w> come A% ma non %iene stampata la %ersione di Ruby, inoltre se non %iene indicato il
nome del programma da linea di comando lo legge dallo standard input.
-e comando> %iene eseguito il comando passato come argomento allop!ione.
Ber una tratta!ione completa di tutte le %oci si faccia riferimento alla pagina del manuale. *ltre che
attra%erso le op!ioni da riga di comando possibile modificare il comportamento dellinterprete
operando sulle %ariabili dambiente. &ueste sono le principali %ariabili utili!!ate da Ruby>
/U'A21'> lista di directory contenenti librerie aggiunte a quelle standard.
/U'A-34> op!ioni addi!ionali da passare allinterprete.
/U'A3.45> lista di directory nel quale Ruby cerca le applica!ioni quando specificato il flag
A8.
/U'A+5&22> persorso della shell di sistema, %alido solo per piattaforme :indo"s e *8K2.
Interactive Ruby
9Interacti%e Ruby, in bre%e irb, una shell che permette di sperimentare in tempo reale col
linguaggio Ruby. Risulta particolarmente utile sia in fase di apprendimento sia in fase di
2sperimenta!ione4. *ltre ad essere un interprete interatti%o fornisce alcune utili fun!ionalit5 tra le
quali spicca la 2)ab Completition4, la possibilit5 di creare sottosessioni e la presen!a di alcuni
comandi di controllo CLobs, fg, cb, conf, #ill, MD.
Come linterprete anche irb pre%ede op!ioni da linea di comando>
$ irb --help
Usage: irb*rb [options] [programfile] [arguments]
-f +uppress read of BC*irbrc
-m 'c mode (load mathn, fraction or matri# are a,ailable)
-d +et $%&'U( to true (same as )ruby -d))
-r load-module +ame as )ruby -r)
-1 path +pecify $2-.%3.45 directory
--inspect Use )inspect) for output (default e#cept for bc mode)
--noinspect %on)t use inspect for output
--readline Use /eadline e#tension module
--noreadline %on)t use /eadline e#tension module
--prompt prompt-mode
--prompt-mode prompt-mode
+witch prompt mode* 3re-defined prompt modes are
)default), )simple), )#mp) and )inf-ruby)
--inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs*
+uppresses --readline*
--simple-prompt +imple prompt mode
--noprompt 7o prompt mode
--tracer %isplay trace for each e#ecution of commands*
--bac"-trace-limit n
%isplay bac"trace top n and tail n* 4he default ,alue is =D*
--irbdebug n +et internal debug le,el to n (not for popular use)
-,, --,ersion 3rint the ,ersion of irb
8pendiamo qualche parola in pi( su irb, che utili!!eremo molto nel corso della guida. <ediamo
come %a eseguito.
'li utenti di 9inu;, e dei sistemi J$INAli#e, de%ono semplicemente aprire un terminale qualsiasi e
scri%ere 2irb4 seguito da una o pi( op!ioni. In ambiente :indo"s possibile eseguire fxri
CInteracti%e Ruby @elp O ConsoleD che oltre alla shell irb ci mostra un utile bro"ser della
documenta!ione Ccome mostrato in figura .D. In alternati%a possibile accedere a irb anche
attra%erso FreeRIDE, atti%ando la %ista attra%erso lapposita icona 2IR+4 oppure sele!ionandola
nel menu 2<ie"4.
Eigura .> lambiente E;ri Cclic per ingrandireD
RDoc e Ri
RFoc uno strumento che produce documenta!ione estraendola dai file sorgente. Broduce sia
documenta!ione html leggibile da qualsiasi bro"ser sia documenta!ione formattata per lutility ri.
Ber ora tutto ma torneremo sullargomento in un prossimo capitolo.
eRuby
eRuby Cembedded RubyD uno strumento che permette di inserire codice ruby allinterno di altri
file, ad esempio nei file @)39 creando di fatto delle pagine dinamiche. Ci sono due
implementa!ioni di eRuby> erb ed eruby. Fiamo uno sguardo ad erb che %iene distribuito con Ruby.
In pratica erb anali!!a il file che gli %iene passato come argomento alla ricerca di particolari
delimitatori. In particolare quando incontra qualcosa del genere
EF istruGioni ruby FH
esegue il codice presente tra PQ e QR quando incontra
EF< espressione FH
%aluta lespressione e ne restituisce il %alore infine ogni linea che ini!ia col carattere 2Q4 %iene
%alutata come codice ruby e PS M QR rappresenta un commento.
7d esempio se passiamo a erb il testo seguente
F str < Iao#omo#oaI
EF< str FH al contrario si legge EF< str*re,erse FH
otterremo come output>
ao#omo#oa al contrario si legge ao#omo#oa
*%%iamente questo un esempio banale, ma erubyKerb rappresenta una %alida alternati%a ai
linguaggi B@B, 78B e simili per la crea!ione di pagine dinamiche.
Testrb
Jn semplice esecutore di test C4est::UnitD dispone di di%erse interfacce grafiche molto minimali
Ct#, gt#, fo;D e di una modalit5 da linea di comando.
Le librerie di base
*ltre ai programmi appena %isti, installando ruby in uno dei modi che %edremo nel prossimo
capitolo, otterremo anche le librerie di base. In ambiente 9inu; si tro%eranno in CusrClibCrubyC
mentre sotto :indo"s, se si sceglie il percorso consigliato dallinstaller, saranno nella directory
c:rubylibruby. In tali directory di norma si tro%ano 0 sottodirectory>
=*J: contiene i moduli e le estensioni standard
gems: contiene le librerie e le applicazioni installate con lutility RubyGems
siteruby: contiene i moduli e le estensioni di terze parti, aggiunte dallo sviluppatore e
che non fanno parte della distribuzione base.
RubyGems
*ltre ai tool precedenti, distribuiti con Ruby, risulta di grande utilit5 Ruby'ems, un frame"or# per
la gestione di librerie e applica!ioni distribuite sotto forma di appositi pacchetti C2gems4D. Come
tutti i pac#age manager che si rispettano permette di cercare, installare, disinstallare e aggiornare
librerie e applica!ioni, e inoltre ne permette la con%i%en!a di di%erse %ersioni. 7nche in questo caso,
in una prossima puntata, mostreremo come distribuire una nostra applica!ione sotto forma di gem.
IDE
,sistono di%ersi ambienti di s%iluppo CIF,, Integrated Fe%elopment ,n%ironmentsD, sia pensati
espressamente per Ruby sia adattati da altri linguaggi. )ra i principali tro%iamo>
FreeRI! : progetto open source, scritto interamente in Ruby. "unico difetto # una certa
lentezza nei rilasci di nuove versioni e nellaggiunta di nuove caratteristiche.
Ruby evelopment $ool %R$&: plug'in per !clipse, (uindi porta con se tutti i difetti e i pregi
di eclipse.
)omodo : progetto commerciale di *ctive+tate, # uno degli I! pi, completi e, ad oggi,
lunico a comprendere un G-I builder integrato. )omodo !ditor # invece liberamente
scaricabile.
*rachnoRuby : progetto commerciale, non # ancora completamente stabile e richiede
re(uisiti minimi di sistema abbastanza alti. Inoltre lo sviluppo della versione "inu. procede
pi, lentamente di (uella per /indo0s, mentre la versione per 1ac 2+ 3 non # stata ancora
rilasciata.
Ruby evelopment !nvironment %R!&: progetto non commerciale ancora in fase di
sviluppo. !siste solo per /indo0s.
*ltre agli IF, appena %isti sono molti utili!!ati dalla comunit5 Ruby anche alcuni editor con
caratteristiche a%an!ate per gli s%iluppatori. 7 tale proposito %anno sicuramente citati, oltre ai
classici <im ed ,macs, 8ci), e )e;t3ate il primo open source e disponibile per :indo"s e 9inu;
mentre il secondo commerciale e disponibile solo per 3ac *8 N.
Altre implementazioni
Concludiamo questo capitolo citando le altre implementa!ioni del linguaggio Ruby. 8u tutte %a
ricordato per complete!!a e importan!a TRuby, unimplementa!ione del Ruby scritta in Ta%a. Con
TRuby possibile, tra laltro, chiamare gli oggetti Ta%a dallinterno delle applica!ioni Ruby e quindi
sfruttare tutti i %antaggi del frame"or# di casa 8un. ,sistono anche implementa!ioni, per6 non
ancora mature, per il frame"or# .$,) e sono RubyC9R e Ruby.$,).
Fopo questa bre%e carrellata dei principali strumenti, che useremo nel corso della guida, andiamo a
%edere come installarli sul nostro sistema qualora non siano gi5 presenti.
Windows
7nche gli utenti :indo"s hanno di%erse possibilit5, possono installare i binari oppure utili!!are il
*ne Clic# Installer.
Installando il 2Ruby Installer for :indo"s4, che la scelta consigliata, a%remo in poche mosse
unambiente di programma!ione completo. Brecisamente tro%eremo sul nostro disco, oltre
o%%iamente allinterprete Ruby completo di sorgenti con le sue utility e le librerie di base, anche le
utility Ruby'ems e Ra#e, alcune utili librerie come E;Ruby, *pen'9, N39Barser, @)39Barser,
RubyF+I, la prima edi!ione del libro 2Brogramming Ruby4, e utili tool come lIF, EreeRIF, Cin
figura 2D e leditor 8ci),.
Eigura 2> EreeRIF,, lIF, gratuito per Ruby
Mac
Falla %ersione .0.U di 3ac*8 N Ruby installato di default. Ber le %ersioni precedenti possibile
usare i Far"inBorts ed installarlo con un semplice 2port install ruby4.
RubyGems
I sorgenti di Ruby'ems sono disponibili su Internet e si installano semplicemente con il comando
2ruby setup.rb4.
Altro
Infine possibile pro%are Ruby sen!a installare nulla, basta puntare il proprio bro"ser "eb su )ry
RubyV. 7 questo indiri!!o si tro%a una shell interatti%a di Ruby pronta alluso con tanto di tutorial di
base per i primi passi.
Fopo questa necessaria introdu!ione a Ruby e ai suoi gioielli, cominceremo dalla prossima puntata
a illustrare il linguaggio %ero e proprio.
Convenzioni in Ruby
Brima di introdurre i principali aspetti del linguaggio diamo uno sguardo %eloce alle principali
con%en!ioni sui nomi e sui commenti. 7ltre con%en!ioni, e semplici suggerimenti sullo stile,
%erranno introdotte durante lo s%olgimento della guida.
Nomi
Ini!iamo a %edere le con%en!ioni sui nomi delle %ariabili, dei metodi e delle classi. Fi seguito una
rapida carrellata con degli esempi esplicati%i>
"e variabili locali devono iniziare con una lettera minuscola o col carattere underscore.
"e variabili globali con il segno $.
"e variabili di istanza con il segno K.
"e variabili di classe con due segni K.
"e costanti con una lettera maiuscola.
,cco degli esempi>
nome < ILatGI ? nome M una ,ariabile locale
Lesi < => ? Lesi M una costante
L&+1 < => ? anche L&+1 M una costante
Klinguaggio < IrubyI ? Klinguaggio M una ,ariabile di istanGa
K2inguaggio < IrubyI ? anche K2inguaggio M una ,ariabile di istanGa
$anno < >00N ? $anno M una ,ariabile globale
KKcounter < 0 ? KKcounter M una ,ariabile di classe
Inoltre i nomi delle classi, e dei moduli, de%ono ini!iare con la lettera maiuscola, mentre i nomi dei
metodi e dei suoi parametri de%ono ini!iare per lettera minuscola o per underscore 2W4. 7d esempio>
module (eometria
class Ouadrato
def disegna
9e parole chia%e del Ruby, che come accade per tutti i linguaggi non possono essere utili!!ate in
nessun altro modo, sono>
'&(17 &7% alias and begin brea" case class
def definedP do else elsif end ensure
false for if in module ne#t nil not
or redo rescue retry return self super then
true undef unless until when while yield
$e scopriremo il significato nel corso della guida.
Commenti
I commenti sono identificati dal segno S, considerato commento tutto quello che lo segue fino alla
fine della riga>
a < = ? Ouesto M un commento*
? 2)intera riga M un commento
In alternati%a possibile inserire pi( righe di commento tra i tag <begin e <end, in questo modo>
<begin
Ouesto M un commento
su piQ righe
<end
- possibile anche inserire dei commenti che saranno utili!!ati per generare documenta!ione RFoc
torneremo su questo argomento in un prossimo capitolo.
Documentazione
Come accennato prima, uno strumento fondamentale in fase di apprendimento ri che prende come
argomento il nome di una classe, di un modulo o di un metodo e ne mostra a %ideo una bre%e
descri!ione con tanto di esempi. 7d esempio per sapere cosa fa e come si usa il metodo re%erse
della classe 8tring, che abbiamo usato prima, basta scri%ere>
? ri +tring*re,erse
--------------------------------------------------------- +tring?re,erse
str*re,erse <H newstr
------------------------------------------------------------------------
/eturns a new string with the characters from str in re,erse
order*
IstressedI*re,erse ?<H IdessertsI
In alternati%a al punto si pu6 utili!!are anche il carattere 2S4 Cri +tring?re,erseD per i metodi di
classe si usa in%ece la forma con i due punti 2>>4. 8e non si conosce il nome esatto possibile anche
fornire come argomento una indica!ione par!iale, ad esempio
? ri +tring*re
Lore than one method matched your re:uest* Aou can refine
your search by as"ing for information on one of:
+tring?re,erse@, +tring?replace, +tring?re,erse
In questo caso ci %iene fornito in output una lista di possibili scelte. )orniamo un attimo ai nomi dei
metodi il lettore attento a%r5 di certo notato nelloutput precedente la presen!a, oltre a re,erse, del
metodo re,erse@ e si star5 chiedendo qual la differen!a tra i due. In Ruby c una con%en!ione
che pre%ede che i metodi che terminano con il punto esclamati%o siano metodi distrutti%i che non
creano una nuo%a istan!a ma modificano direttamente il %alore. 7nalogamente ci sono i metodi di
%erifica, i cui nomi terminano per punto interrogati%o, che s%olgono in genere fun!ioni di %erifica e
restituiscono un %alore booleano.
Infine una bre%e nota ripresa da Programming Ruby di Fa%e )homas. 7ggiungendo questa fun!ione
def ri(Rnames)
system(FSri ?Snames*map STnameT name*tosU*Voin(I I)UU)
end
al file di configura!ione .irbrc sar5 possibile utili!!are ri allinterno di irb.
La programmazione ad oggetti
Boich= in apertura abbiamo detto che in Ruby 2ogni cosa un oggetto4, e dato che non uno
slogan, prima di muo%erci in qualsiasi dire!ione andiamo a %edere cosa sono gli oggetti.
Ber permettere a tutti i lettori, anche a quelli che non sono pratici di programma!ione orientata agli
oggetti, di appre!!are al meglio il linguaggio, prima di affrontare largomento dal punto di %ista del
Ruby lo tratteremo in modo generico e molto elementare. *%%iamente chi ha gi5 dimestiche!!a con
gli oggetti pu6 saltare a pi pari questo paragrafo. 8u @)39.it presente una guida approfondita
alla programma!ione ad oggetti.
$ella programma!ione **, come nel mondo reale, un oggetto ha le proprie caratteristiche e i propri
comportamenti. 7d esempio il mio router ha una marca, un modello e un numero di serie e fa delle
determinate cose Cad esempio pu6 connettersi e disconnettersiD.
- possibile 2comunicare4 con gli oggetti attra%erso i messaggi, che non sono altro che richieste di
esecu!ione di unopera!ione. Jnopera!ione qualcosa che loggetto destinatario in grado di
eseguire, ad esempio possiamo chiedere al nostro router di connettersi e di disconnettersi.
Informaticamente parlando, per poter creare un oggetto occorre definire una classe che ne definisce
i metodi e gli attributi in parole po%ere una classe un insieme di oggetti simili che si comportano
allo stesso modo e sono caratteri!!ati dagli stessi attributi.
Fiminuendo il grado di astra!ione e tornando alla programma!ione %era e propria possiamo dire che
un oggetto pu6 essere %isto come un contenitore di dati Cche a questo punto possiamo identificare
con delle semplici %ariabiliD dotato di una serie di fun!ioni Ci metodiD che definiscono uninterfaccia
alloggetto stesso.
Ruby e gli oggetti I
<ediamo come implementata in Ruby la programma!ione orientata agli oggetti. 8cri%iamo un
semplice esempio supponendo di do%er programmare un %ideogame di guerra do%e tra le altre cose
sono presenti dei carri armati e dei camion per il trasporto dei soldati. Rappresentiamo questi
oggetti in Ruby>
class $arro.rmato
def initialiGe
puts I+ono un nuo,o carro armatoI
end
end
class $amion
def initialiGe
puts I+ono un nuo,o camionI
end
end
una %olta definite le classi possiamo istan!iarne degli oggetti. In irb, dopo a%er creato le classi
scri%iamo>
H ca < $arro.rmato*new
+ono un nuo,o carro armato
<H ?E$arro.rmato:0#bNdW>NfcH
H c < $amion*new
+ono un nuo,o camion
<H ?E$amion:0#bNd0NeNJH
<ediamo in ordine cosa abbiamo fatto. Innan!itutto abbiamo creato la classe usando la parola
chia%e class seguita dal nome e abbiamo terminato il codice relati%o alla nostra classe con la
parola chia%e end. 7bbiamo quindi creato il metodo initialiGe che %iene chiamato quando
istan!iamo un nuo%o oggetto con il metodo new. initialiGe quello che in **B si dice un
costruttore che %iene in%ocato ogni %olta che si crea un nuo%o oggetto. 7lcuni linguaggi orientati
agli oggetti come il CGG contemplano anche il metodo distruttore della classe che, in%ocato al
momento del rilascio dellistan!a di un oggetto, si occupa tra le altre cose di deAallocare la memoria
impegnata dalloggetto. $ei linguaggi moderni, come Ruby, Ta%a o CS, le atti%it5 generalmente
s%olte dal distruttore %engono s%olte da sistemi di garbage collection, nel caso di Ruby linterprete
a farsene carico.
)ornando al nostro esempio, initialiGe un normale metodo ed definito dalle parole chia%e
def, seguita dal nome, e dal solito end. ,ssendo un esempio banale il costruttore non fa altro che
dare noti!ia della%%enuta crea!ione delloggetto stampando a %ideo una stringa utili!!ando la
fun!ione puts Cput stringD.
Ber fare un esempio meno banale e per %edere come si passano i parametri ad un metodo
miglioriamo le nostre classi. 8upponiamo di %oler definire al momento della crea!ione degli oggetti
alcuni parametri caratteristici. 7d esempio se %ogliamo indicare quanto carburante e quanti colpi
a%r5 il nostro carro armato al momento della crea!ione ci basta scri%ere>
class $arro.rmato
def initialiGe (colpi, carburante)
Kcarburante < carburante
Kcolpi < colpi
end
end
7nalogamente per i camion, con la differen!a che in%ece dei colpi ci saranno dei posti per i
passeggeri>
class $amion
def initialiGe (posti, carburante)
Kcarburante < carburante
Kposti < posti
end
end
Come abbiamo %isto nel capitolo precedente, Kcarburante, Kcolpi e Kposti sono delle %ariabili
distan!a e sono %isibili da tutti i metodi della classe.
In questo modo alla crea!ione dei nostri nuo%i oggetti %anno passati i parametri relati%i al
carburante, ai colpi e ai posti>
H ca < $arro.rmato*new(=0, =00)
<H ?E$arro.rmato:0#bNd0WXfc Kcolpi<=0, Kcarburante<=00H
c < $amion*new(>0, =00)
<H ?E$amion:0#bNce0YDc Kposti<>0, Kcarburante<=00H
Kcarburante, Kcolpi e Kposti sono detti anche attributi e definiscono come la classe %ista
dallesterno. Ber poter accedere, in lettura, a tali campi occorre creare dei metodi accessori del tipo>
class $arro.rmato
def carburante
Kcarburante
end
def colpi
Kcolpi
end
end
fatto ci6 possiamo scri%ere cose del genere>
H puts ca*carburante
<H =00
H puts ca*colpi
<H =00
Ber poter accedere agli attributi anche in scrittura occorre definire anche in questo caso un apposito
metodo>
class $arro.rmato
def carburante<(carburante)
Kcarburante < carburante
end
def colpi<(colpi)
Kcolpi < colpi
end
end
e quindi siamo in grado di impostare i %alori degli attributi semplicemente con
H ca*colpi < X0
<H X0
H puts ca*colpi
<H X0
9a gestione degli attributi molto elementare e allo stesso tempo molto tediosa. ,ssendo per6 una
pratica di uso comune, il Ruby fornisce delle comode scorciatoie per la gestione degli attributi>
attrreader, attrwriter, attraccessor e attr. Il nostro codice di%enta in definiti%a>
class $arro.rmato
attr :colpi, true
attr :carburante, true
def initialiGe (colpi, carburante)
Kcolpi < colpi
Kcarburante < carburante
end
end
class $amion
attr :posti, true
attr :carburante, true
def initialiGe (posti, carburante)
Kposti < posti
Kcarburante < carburante
end
end
Il %alore true dopo il nome dellattributo sta ad indicare che la %ariabile anche scri%ibile, in
alternati%a a%remmo potuto usare attrreader e attrwriter oppure attraccessor che
sinonimo di 2attr nomesimbolo, true2, o%%ero scri%ere
attraccessor :posti, :carburante
lo stesso che scri%ere
attr :posti, true
attr :carburante, true
&uesto bre%e esempio mostra tutta lelegan!a del Ruby che fa di tutto per %enire in contro alle
necessit5 dello s%iluppatore sen!a perdere omogeneit5 e leggibilit5.
In realt5 nel nostro caso meglio permettere solo la lettura degli attributi e creare ad esempio un
metodo per la gestione del carburante. 9a nostra classe Camion di%enta dunque>
class $amion
attrreader :posti, :carburante
def initialiGe (posti, carburante)
Kposti < posti
Kcarburante < carburante
end
def rifornimento (:uantita)
Kcarburante Z< :uantita
end
end
*ra non sono pi( lecite istru!ioni del genere
H c*carburante < =00
ma per manipolare lattributo carburante occorre usare il metodo rifornimento>
H c*rifornimento(=00)
9o stesso discorso %ale per laltra classe e gli altri attributi.
Fegli argomenti dei metodi possibile indicare anche il %alore di default, ad esempio definendo
initialiGe in questo modo
def initialiGe (colpi, carburante < =00)
Kcolpi < colpi
Kcarburante < carburante
end
possiamo istan!iare nuo%i oggetti anche passando un solo parametro, per il secondo argomento
%iene considerato il %alore di default
H ca < $arro.rmato*new(X0)
<H ?
&uando si chiama un metodo, luso delle parentesi facoltati%o, o%%ero corretto anche scri%ere>
H ca < $amion*new X0
<H ?
Ber ora, per e%itare confusione fermiamoci qui, torneremo di seguito sugli oggetti trattando
lereditariet5, il polimorfismo e altri aspetti a%an!ati.
!ipi di dati" numeri
Ini!iamo a %edere i tipi fondamentali di ogni linguaggio> i numeri e le stringhe. &ueste ultime le
anali!!eremo nella prossima le!ione.
Il linguaggio Ruby pre%ede lesisten!a di numeri interi e di numeri a %irgola mobile CfloatingA
pointD. I primi sono oggetti delle classi !i#num o 'ignum mentre i secondi sono di tipo !loat. I
numeri che possono essere rappresentati in una "ord Cmeno un bitD sono oggetti della classe
Ei;num, quelli che %anno oltre questo limite sono in%ece istan!e della classe +ignum>
f < =>W
f*class
<H !i#num
b < =>WYXDNJ[0
b*class
<H 'ignum
Ber rappresentare numeri non decimali %a fatto precedere al numero %ero e proprio un indicatore di
base C0b per i binari, 0 per gli ottali, 0d per i decimali e 0; per gli esadecimaliD, ad esempio>
H =0 ? i numeri decimali sono preceduti da 0d che per\ pu\ essere omesso
<H =0
H 0=0 ? i numeri ottali sono preceduti da uno 0
<H J
H 0#=0 ? i numeri esadecimali sono preceduti da 0#
<H =D
H 0b=0 ? i numeri binari sono preceduti da 0b
<H >
,ssendo i numeri oggetti di una determinata classe possiamo applicare ad essi i metodi pre%isti
dalle rispetti%e classi. I principali metodi pre%isti da Ei;num e +ignum sono>
opera!ioni aritmetiche di base CG, A, X, K, di%, Q, modulo, XX, Y unarioD
opera!ioni sui bit CZ, [, O, \, PP, RRD
altre opera!ioni aritmetiche>
o %alore assoluto CabsD> -=>W*abs -H =>W
o dimensione in byte Csi!eD> =00*siGe -H Y
o opera!ioni di con%ersione CtoWf, toWs, toWsymD> =*tos -H I=I, =*tof -H =*0
7ltri metodi sono ereditati dalle classi 1nteger e 7umeric poich= entrambe le classi deri%ano da
Integer che a sua %olta deri%a da $umeric. 7bbiamo ad esempio chr, floor, ne#t, toi, step e
molti altri.
9a classe Eloat oltre ai metodi base %isti per Ei;num e a quelli ereditati da $umeric pre%ede tra
laltro>
infiniteP che restituisce A., G. o nil a seconda che il %alore sia pari a meno infinito, pi(
infinito o un numero finito> (=*0)*infiniteP -H nil, (Z=*0C0*0)*infiniteP -H =
nanP restituisce true se il %alore un numero non %alido secondo gli standard I,,,.
Ber ulteriori dettagli su questi e altri metodi consiglio %i%amente luso di ri sulle classi Ei;num,
+ignum, Integer e $umeric.
!ipi di dati" stringhe
Come abbiamo %isto in preceden!a una delle maggiori influen!e del linguaggio Ruby il Berl e da
questo eredita, tra laltro, una potente e a%an!ata gestione del testo.
9e stringhe, sequen!e di caratteri racchiusi tra %irgolette C2D o tra singoli apici C]D, sono delle istan!e
della classe +tring. - pre%isto un a%an!ato sistema di accesso ai singoli caratteri delle stringhe
attra%erso il metodo ^_. 7d esempio possiamo accedere a qualsiasi carattere di una stringa
indicandone semplicemente lindice>
H str < I$iao Londo@I
<H I$iao Londo@I
H str*class
<H +tring
H str[0]
<H DN
%iene restituito un intero che il %alore del codice 78CII corrispondente nel nostro caso al carattere
2C4. Ber ricon%ertirlo in carattere si utili!!a il metodo chr %isto prima>
H str[0]*chr
<H I$I
- possibile con ^_ anche accedere a sottostringhe>
H str[0**W]
<H I$iaoI
H str[0***W]
<H I$iaI
H str[0,Y]
<H I$iaoI
Fo%e 0..0 e 0M0 sono dei range, le due cifre rappresentano gli estremi dellinter%allo da prendere
in considera!ione se si utili!!ano i tre punti CMD il secondo estremo %iene escluso. Bassando in%ece
come argomenti due interi, ad esempio 0 e `, estraiamo da str la sottostringa che ini!ia al carattere
con indice 0 Cla prima lettera della prima parolaD e che ha lunghe!!a pari a ` caratteri. Inserendo
degli indici negati%i il conteggio a%%iene in%ece dalla fine della stringa>
H str[-D**-=]
<H ILondo@I
H str[-D,D]
<H ILondo@I
Jtili!!ando una stringa come argomento %iene restituito il %alore nil se questa non presente e la
stringa stessa in caso contrario>
H str[I5elloI]
<H nil
H str[ILondoI]
<H ILondoI
Infine possibile anche passare come argomento unespressione regolare>
H str[CwZsC]
<H I$iao I
torneremo in dettaglio sullargomento in un prossimo capitolo. In alternati%a a ^_ possibile usare il
metodo slice.
7nalogo a ^_ il metodo di assegna!ione ^_a, lo%%ia differen!a che in questo caso %iene eseguita
unassegna!ione alla por!ione di stringa determinata dallargomento di ^_a. 7nche in questo caso
possono essere passati come argomenti un intero, due interi, un range, unespressione regolare o
una stringa>
H str < I$iao Londo@I
H str[Y] < I,I
H str[0**W] < I5elloI
H str[-D,X] < I;orldI
H str
<H I5ello,;orld@I
<ediamo infine alcuni utili metodi applicabili alle stringhe>
# moltiplica la nostra stringa
o 2Ciao 4 X 2 AR 2Ciao Ciao 2
G concatena due stringhe
o 2Ciao 4 G 23ondo4 AR 2Ciao 3ondo4
capitalize restituisce una copia della stringa con il primo carattere maiuscolo
o 2ciao4.capitali!e AR 2Ciao4
do$ncase e upcase restituiscono rispetti%amente una copia della stringa con tutte le lettere
minuscole e con tutte le lettere maiuscole
o 2Ciao4.upcase AR 2CI7*4
o 2Ciao4.do"ncase AR 2ciao4
s$apcase restituisce una stringa con il case dei caratteri in%ertito, minuscole al posto di
maiuscole e %ice%ersa
chop elimina lultimo carattere da una stringa
o 2Ciaon4.chop AR 2Ciao4
o 2Ciao4.chop AR 2Cia4
chomp elimina dalla fine della stringa lelemento separatore passato come argomento, se
in%ocato sen!a argomento rimuo%e i %alori n, r o entrambi
o 2Ciaon4.chomp AR 2Ciao4
o 2Ciao4.chomp AR 2Ciao4
o 2Ciao4.chompC2ao4D AR 2Ci4
sub e gsub sostituiscono rispetti%amente la prima occorren!a e tutte le occorren!e
dellespressione regolare passata come primo argomento e lo sostituiscono con il %alore del
secondo argomento
o 2ciao mondo4.gsubCKoK, ]XD AR 2ciaX mXndX4
o 2ciao mondo4.subCKoK, ]XD AR 2ciaX mondo4
split di%ide la stringa in sottostringhe in conformit5 al delimitatore passato come argomento.
Come delimitatore possibile usare sia stringhe che espressioni regolari, il %alore di default
il carattere bianco
o 2ciao mondo4.split AR ^bciaob, bmondob_
o 2ciao mondo4.splitC]oD AR ^bciab, b mb, bndb_
tr prende due stringhe come argomenti e sostituisce i caratteri del primo argomento con i
corrispondenti caratteri del secondo argomento
o 2ciao4.trC2c4, 2m4D AR 2miao4
o 2ciao4.trC]aAy, ]bA!D AR 2dLbp4
7ltri metodi molto utili per la formatta!ione del testo sono strip, lstrip, rstrip, lVust, rVust
e center. 8ono metodi molto semplici e intuiti%i %ediamo solo qualche esempio %eloce>
H IciaoI*center(>0)
<H I ciao I
H IciaoI*lVust(>0)
<H Iciao I
H IciaoI*rVust(>0)
<H I ciaoI
I ciao I*lstrip
<H Iciao I
I ciao I*rstrip
<H I ciaoI
H I ciao I*strip
<H IciaoI
Fi quasi tutti i metodi %isti in questo paragrafo ne esiste anche la %ersione distrutti%a che, in%ece di
restituire una copia della stringa opportunamente modificata, modifica direttamente la stringa
originaria. )orneremo sulle stringhe nel capitolo sulle espressioni regolari.
%locchi e iteratori
In questo capitolo faremo una panoramica sui blocchi e sugli iteratori, in modo da a%ere gli
strumenti necessari per affrontare i prossimi capitoli. 7nche se sono caratteristiche presenti in altri
linguaggi da lungo tempo, il Ruby che ha reso lutili!!o di questi potenti strumenti
incredibilmente semplice.
locc!i e iteratori
Ini!iamo con un paio di defini!ioni. Jn blocco sintatticamente una por!ione di codice compresa
tra le parole chia%e do e end oppure tra una coppia di parentesi graffe c e d con%en!ionalmente si
utili!!a la seconda forma per blocchi che occupano una sola riga. Jn iteratore in%ece un normale
metodo che accetta come argomento un blocco, o%%ero una fun!ione anonima che %iene eseguita sui
parametri passatigli dalliteratore. - molto pi( semplice di quello che sembra, %ediamo un semplice
esempio per chiarire un po le cose>
H str < I$iao LondoI
H str*eachbyte STcT puts c*chrU
$
i
a
o
L
o
n
d
o
7bbiamo utili!!ato literatore eachbyte della classe +tring che passa ogni byte della stringa
come parametro al blocco tra parentesi graffe. 7bbiamo anche passato un parametro CcD tra il
metodo e il blocco. 9a %ariabile c, locale al blocco, assume quindi di %olta in %olta il %alore passato
dal metodo, nel nostro esempio i singoli caratteri delle stringa.
- possibile passare dei parametri anche alliteratore come a qualsiasi altro metodo. 7d esempio
literatore each, o eachline, della classe 8tring accetta come argomento il %alore del separatore Cn
il %alore di defaultD>
H str*each STcT puts cU
$iao Londo
H str*each() )) STcT puts cU
$iao
Londo
<edremo la grande utilit5 degli iteratori quando parleremo degli array e delle altre strutture dati.
Brima di concludere diamo un altro sguardo ai blocchi e %ediamo come %anno chiamati dallinterno
di un metodo. 8ubito un esempio che poi commenteremo>
def chiama
puts I+ono nel metodoI
yield
end
chiama S puts I+ono nel bloccoI U
eseguendo questo codice otterremo il seguente output>
+ono nel metodo
+ono nel blocco
Ber richiamare il blocco abbiamo usato listru!ione yield, che non fa altro richiamare il blocco
associato al metodo che lo contiene. - possibile utili!!are pi( %olte yield allinterno di un metodo>
def chiama
yield
puts I+ono nel metodoI
yield
end
e anche passare parametri al blocco tramite yield>
def chiama
puts I+ono nel metodoI
yield(=00)
end
chiama S TnT puts I+ono nel blocco e il parametro ,ale: ?SnUI U
In questo modo a%remo in output
+ono nel metodo
+ono nel blocco e il parametro ,ale: =00
7priamo una bre%e parentesi sul significato di ?SespressioneU allinterno della stringa passata a
puts. In pratica il codice contenuto allinterno delle parentesi %iene eseguito e il risultato
trasformato in stringa, e nel nostro esempio il tutto stampato.
Infine possiamo creare un blocco contenente delle normali espressioni>
begin
?espressione=
?espressione>
?***
end
Il %alore dellultima espressione %alutata sar5 anche il %alore del blocco. Come %edremo tra qualche
capitolo beginCend risulta di grande utilit5 soprattutto nella gestione delle ecce!ioni.
Jn array pu6 essere %isto come una lista di oggetti non necessariamente dello stesso tipo. 'li array
sono istan!e della classe .rray e %anno dunque creati nel seguente modo>
arr < .rray*new
in alternati%a possibile creare un array anche scri%endo semplicemente>
arr < []
in entrambi i casi creeremo un array %uoto. 8e in%ece si de%e creare un array non %uoto possibile
passare una lista di %alori separati da %irgole>
arr < [=, >, ItreI, I10I]
in questo modo abbiamo creato un array di quattro elementi, due interi e due stringhe. - possibile
chiamare il metodo new anche con uno o due parametri, il primo indica le dimensioni dellarray
mentre il secondo il %alore di ini!iali!!a!ione>
H arr < .rray*new(W)
<H [nil, nil, nil]
arr < .rray*new(W, =00)
<H [=00, =00, =00]
Ber le altre forme del metodo new rimando alla documenta!ione ufficiale.
Ber inserire nuo%i elementi nellarray o per modificare quelli esistenti si utili!!a il metodo ^_a
H arr < [=, >, >]
<H [=, >, >]
H arr[>] < W
<H W
H arr
<H [=, >, W]
8i pu6 anche indicare un indice superiore alle dimensioni dellarray, in tal caso larray si estende
automaticamente e gli elementi compresi tra il lindice indicato e lultimo elemento dellarray sono
impostate a nil>
H arr[J] < [
<H [
H arr
<H [=, >, W, nil, nil, nil, nil, nil, []
Come indice possibile indicare due interi che rappresentano rispetti%amente lindice di ini!io e il
numero di elementi da sostituire con il %alore passato>
H arr < [=, >, W, Y, X]
<H [=, >, W, Y, X]
H arr[0,>] < [I1I, I11I]
<H [I1I, I11I]
H arr
<H [I1I, I11I, W, Y, X]
H arr[>,W] < I111I
<H I111I
H arr
<H [I1I, I11I, I111I]
in questo modo abbiamo creato un array di cinque elementi e poi abbiamo sostituito i primi due
Cindice 0 e numero di elementi 2D con i %alore 2I4 e 2II4. 7bbiamo infine sostituito i restanti tre
elementi con il %alore 2III4. 7nalogamente pu6 essere usato anche un range con o%%io significato,
lesempio precedente pu6 essere riscritto cos?>
H arr < [=, >, W, Y, X]
<H [=, >, W, Y, X]
H arr[0**=] < [I1I, I11I]
<H [I1I, I11I]
H arr
<H [I1I, I11I, W, Y, X]
H arr[>**Y] < I111I
<H I111I
H arr
<H [I1I, I11I, I111I]
Ber il resto, per quel che riguarda i range, %algono le stesse propriet5 gi5 %iste per le stringhe.
9accesso agli elementi a%%iene attra%erso il metodo ^_, o il metodo slice che pre%ede anche una
forma distrutti%a slice@ che elimina dallarray gli elementi indicati dallindice. Come per ^_a,
anche ^_, pu6 prendere come argomenti un intero, oppure due interi o infine un range.
Jn altro metodo per inserire elementi in un array rappresentato dai metodi EE e push che
inseriscono i nuo%i %alori in fondo allarray che si comporta in questo caso come una pila Cstac#D>
H arr < [=, >, W]
<H [=, >, W]
H arr EE X EE D
<H [=, >, W, X, D]
H arr*push(N,J)
<H [=, >, W, X, D, N, J]
7llopposto il metodo pop in%ece elimina lultimo elemento di un array>
H arr*pop
<H J
H arr
<H [=, >, W, X, D, N]
Jn altro metodo per inserire %alori in un array gi5 esistente insert che prende come argomenti
un indice ed uno o pi( oggetti da inserire nellarray>
H arr < [=0, W0, Y0]
<H [=0, W0, Y0]
H arr*insert(=, >0)
<H [=0, >0, W0, Y0]
possibile anche indicare due o pi( oggetti, in questo modo il primo %err5 inserito nella posi!ione
indicata dallindice e gli altri di seguito>
H arr*insert(Y, X0, D0, N0)
<H [=0, >0, W0, Y0, X0, D0, N0]
7gli array possibile anche applicare le opera!ioni G, A, X, O. Il metodo concatena!ione CGD
restituisce un nuo%o array ottenuto dalla concatena!ione di due array>
H a < [IaI, IeI, IiI]
<H [IaI, IeI, IiI]
H b < [IoI, IuI]
<H [IoI, IuI]
H c < a Z b
<H [IaI, IeI, IiI, IoI, IuI]
7nalogamente il metodo differen!a restituisce un nuo%o array ottenuto dalla differen!a di due array>
H a < [IaI, IeI, IiI]
<H [IaI, IeI, IiI]
H b < [IaI, IuI]
<H [IaI, IuI]
H c < a - b
<H [IeI, IiI]
Il metodo CXD in%ece si comporta in modo di%erso a seconda dellargomento se gli %iene passato un
intero n restituisce un array costituito da n copie dellarray originario>
H a < [IaI, IeI, IiI]
<H [IaI, IeI, IiI]
H a R >
<H [IaI, IeI, IiI, IaI, IeI, IiI]
8e in%ece allargomento pu6 essere applicato il metodo tostr, e non un intero, a%remo come
risultato una stringa costituita dagli elementi dellarray inter%allati dalla stringa argomento>
H a < [IaI, IeI, IiI]
<H [IaI, IeI, IiI]
H a R I***I
<H Ia***e***iI
Infine c il metodo interse!ione COD che restituisce un nuo%o array costituito dagli elementi
comuni dei due array>
H a < [IaI, IeI, IiI]
<H [IaI, IeI, IiI]
H b < [IiI, IeI, IiI]
<H [IiI, IeI, IiI]
H a ] b
<H [IeI, IiI]
7ltri metodi di grande utilit5 pratica sono>
clear che rimuo%e tutti gli elementi
compact rimuo%e solo gli elementi nil
delete rimuo%e gli elementi passati come argomento
empty& che restituisce true se larray %uoto, false in caso contrario
include& restituisce true se lelemento passato come argomento presente nellarray
index restituisce lindice della prima occorren!a delloggetto passato come argomento
'oin restituisce una stringa ottenuta dalla concatena!ione degli elementi dellarray,
possibile anche fornire come argomento il separatore
o ^., 2, 0_.Loin AR 2.20e
o ^., 2, 0_.LoinC2M4D AR 2.M2M0e
length, size e nitems restituiscono il numero di elementi con la differen!a che lultimo
metodo non tiene conto degli elementi nil
reverse crea un nuo%o array con lordine degli elementi in%ertito
sort restituisce un nuo%o array con gli elementi ordinati
o ^., ``, 6, 2 ,`_.sort AR ^., 2, `, 6, ``_
Ber la lista completa dei metodi rimando al comado ri .rray.
Concludiamo con i principali iteratori applicabili alle istan!e della classe .rray.
Il metodo each esegue il blocco per ogni elemento dellarray passandolo come parametro. 7nalogo
il comportamento di re,erseeach con la differen!a che gli elementi dellarray %engono passati
al blocco in ordine in%erso>
H arr < [IrossoI, IbiancoI, IneroI]
<H [IrossoI, IbiancoI, IneroI]
H arr*each STcoloreT puts coloreU
rosso
bianco
nero
<H [IrossoI, IbiancoI, IneroI]
H arr*re,erseeach STcoloreT puts coloreU
nero
bianco
rosso
<H [IrossoI, IbiancoI, IneroI]
eachinde# in%ece di passare gli elementi come parametri passa gli indici di tali elementi>
H arr*eachinde# STindiceT puts indiceU
0
=
>
<H [IrossoI, IbiancoI, IneroI]
Il metodo collect e il suo sinonimo map, ereditati da ,numerable, in%ocano il blocco per ogni
elemento dellarray e restituiscono un array costituito dagli elementi modificati dal blocco>
H arr < [=, >, W]
<H [=, >, W]
H arr*collectSTnT nRWU
<H [W, D, []
deleteif elimina dallarray tutti quegli elementi per il quale la %aluta!ione nel blocco restituisce
%alore true. 8imilmente si comportano select e reVect.
(ash
'li hash, istan!e della classe @ash, sono liste di coppie di chia%i e %alori. 7 differen!a degli array
in%ece degli indici numerici, che identificano la posi!ione nellarray dellelemento, negli hash
tro%iamo delle chia%i che possono essere di tipo qualsiasi. In Ruby gli hash sono racchiusi tra
parentesi graffe e ogni coppia e separata dallaltra da una %irgola, mentre tra le chia%i e i %alori ci
de%e essere il simbolo <H
Come gli array anche gli hash possono essere creati in %ari modi, innan!itutto scri%endo
direttamente le coppie chia%eA%alore tra parentesi graffe
H hsh < SInomeI <H I2e,I, IpatronimicoI <H I7i"olae,icI, IcognomeI <H I4olstoVIU
<H SIcognomeI<HI4olstoVI, InomeI<HI2e,I, IpatronimicoI<HI7i"olae,icIU
in alternati%a si pu6 utili!!are il metodo ^_
H hsh < 5ash[InomeI, I1,anI, IpatronimicoI, I+ergee,icI, IcognomeI, I4urgene,I]
<H SIcognomeI<HI4urgene,I, InomeI<HI1,anI, IpatronimicoI<HI+ergee,icIU
o anche, unendo i modi precedenti, per maggiore chiare!!a>
H hsh < 5ash[InomeI <H I!edorI, IpatronimicoI <H ILichaVlo,icI, IcognomeI <H
I%ostoe,s"iVI]
<H SIcognomeI<HI%ostoe,s"iVI, InomeI<HI!edorI, IpatronimicoI<HILichaVlo,icIU
Infine possibile creare un hash %uoto con il metodo new
H hsh < 5ash*new
<H SU
tale hash %a poi popolato, come abbiamo %isto per gli array, con il metodo ^_a con la differen!a che
in%ece dellindice %a indicata la chia%e>
H hsh[InomeI] < I0ladimirI
<H I0ladimirI
H hsh[IpatronimicoI] < I0ladimiro,icI
<H I0ladimiro,icI
H hsh[IcognomeI] < ILaVa"o,s"iVI
<H ILaVa"o,s"iVI
H hsh
<H SIcognomeI<HILaVa"o,s"iVI, InomeI<HI0ladimirI, IpatronimicoI<HI0ladimiro,icIU
9a stessa sintassi si utili!!a per accedere ai %alori con il metodo ^_. Ber elencare in%ece tutte le
chia%e e i %alori di un hash si utili!!ano i metodi "eys e ,alues>
H hsh*"eys
<H [IcognomeI, InomeI, IpatronimicoI]
H hsh*,alues
<H [ILaVa"o,s"iVI, I0ladimirI, I0ladimiro,icI]
- possibile inoltre indicare un %alore di default che %iene restituito qualora si utili!!a una chia%e
non esistente>
H hsh*default < Ierrore@I
<H Ierrore@I
H hsh[InaGionalit^I]
<H Ierrore@I
)ale %alore pu6 essere impostato anche al momento della crea!ione passando il %alore di default
come argomento a new.
*ltre a buona parte degli iteratori che abbiamo %isto per gli array, gli hash ne hanno di propri che
permettono di sfruttare al meglio la loro struttura.
*ltre a each, che in questo caso passa al blocco sia la chia%e che il %alore come parametri, abbiamo
i metodi each"ey e each,alue che rispetti%amente passano la chia%e e il %alore al blocco che
%iene eseguito come al solito su ogni elemento>
H hsh < SInomeI <H I2e,I, IpatronimicoI <H I7i"olae,icI, IcognomeI <H I4olstoVIU
H hsh*each ST", ,T puts I?S"U: ?S,UIU
cognome: 4olstoV
nome: 2e,
patronimico: 7i"olae,ic
H hsh*each"ey ST"T puts "U
cognome
nome
patronimico
H hsh*each,alue ST,T puts ,U
4olstoV
2e,
7i"olae,ic
)ipico degli hash anche il metodo has,alueP che restituisce true se il %alore passato come
argomento presente nellhash. 7nalogamente, ma per le chia%i, opera has"eyP. Rimando come
al solito alla documenta!ione ufficiale per lelenco completo dei metodi della classe @ash.
If e unless
I"
Ini!iamo dando uno sguardo a if. 8or%oliamo sul significato di questo costrutto, noto a chiunque
conosca labc della programma!ione, e passiamo direttamente alla sintassi con un esempio>
if n << = then
puts I7 ,ale unoI
elsif n << > then
puts I7 ,ale dueI
else
puts I7 non ,ale ne uno ne dueI
end
- possibile omettere, qualora non necessario, sia il ramo elseif sia il ramo else e arri%are alla
forma base
if espressione then
istruGione
end
anche possibile sostituire alla parola chia%e then i due punti C:D, o anche ometterla del tutto se il
nostro if scritto su pi( linee. 9esempio di prima di%enta dunque>
if n << =
puts I7 ,ale unoI
elsif n << >
puts I7 ,ale dueI
else
puts I7 non ,ale ne uno ne dueI
end
Bossiamo inserire unespressione if anche in coda ad una normale istru!ione
puts I7 M maggiore di dieciI if n H =0
#nless
*pposto allif abbiamo lo statement unless che esegue le istru!ioni associate allespressione che
risulta falsa>
unless n H =0
puts I7 non M maggiore dieciI
else
puts I7 M maggiore di dieciI
end
7nche dellunless ne esiste una %ersione modificatrice di istru!ione>
puts I7 M maggiore di dieciI unless n E =0
Jna forma ancora pi( ermetica pre%ede luso delloperatore P nel seguente modo>
segno < n H< 0 P Ipositi,oI : Inegati,oI
se la condi!ione %era %iene eseguita la prima espressione, se falsa la seconda. - buona norma
usare questa sintassi solo nei casi in cui non %a a scapito della leggibilit5, uno dei punti di for!a del
Ruby.
Infine come eserci!io riscri%iamo il metodo rifornimento dellesempio che abbiamo scritto in
preceden!a tenendo contro della capacit5 massima del serbatoio. Innan!itutto bisogna creare una
%ariabile per la capacit5 massima, e poi non ci resta che controllare se la quantit5 di carburante che
%ogliamo immettere pi( quella gi5 presente nel serbatoio non sia superiore alla capacit5 stessa. In
caso affermati%o eroghiamo solo la quantit5 di carburante necessaria per un pieno.
8cri%endo il tutto in modo didattico otteniamo il codice seguente>
$.3.$14.L._+&/'.4-1- < =00
def rifornimento (:uantita)
if (Kcarburante Z :uantita) H $.3.$14.L._+&/'.4-1- then
:uantitanecessaria < $.3.$14.L._+&/'.4-1- - Kcarburante
Kcarburante Z< :uantitanecessaria
puts I$arburante erogato: ?S:uantitanecessariaUI
else
Kcarburante Z< :uantita
puts I$arburante erogato: ?S:uantitaUI
end
puts I$arburante totale: ?SKcarburanteUI
end
,liminando le %ariabili ridondanti e le ripeti!ioni arri%iamo ad un risultato sicuramente migliore>
def rifornimento (:uantita)
if (Kcarburante Z :uantita) H $.3.$14.L._+&/'.4-1- then
:uantita < $.3.$14.L._+&/'.4-1- - Kcarburante
end

Kcarburante Z< :uantita
puts I$arburante erogato: ?S:uantitaUI
puts I$arburante totale: ?ScarburanteUI
end
Eatto questo possiamo scri%ere>
c < $amion*new(X0, W0)
c*rifornimento([0)
ed otteniamo in output il giusto risultato>
$arburante erogato: N0
$arburante totale: =00
In alternati%a a%remmo potuto scri%ere in modo pi( conciso, su una unica riga, anche in questo
modo>
def rifornimento (:uantita)
:uantita < (Kcarburante Z :uantita) H $.3.$14.L._+&/'.4-1- P
$.3.$14.L._+&/'.4-1- - Kcarburante : :uantita
Kcarburante Z< :uantita
puts I$arburante erogato: ?S:uantitaUI
puts I$arburante totale: ?ScarburanteUI
end
Case
n molti casi casi in alternati%a a if, e unless, pi( comodo e pi( chiaro utili!!are il costrutto case.
%ediamolo in dettaglio. 9a sintassi classica la seguente>
case command
when IstartI
puts Ia,,io in corso***I
when IstopI
puts Iarresto in corso***I
else
puts I$omandi: startCstopI
end
9istru!ione che segue lelse rappresenta il ramo di default che %iene eseguito se tutte le altre
condi!ioni falliscono. 8e la condi!ione sulla stessa linea dellespressione possibile utili!!are la
parola chia%e then o i due punti ottenendo una sintassi pi( compatta>
case n
when n H =0: puts I7 M maggiore di dieciI
when n E =0: puts I7 M minore di dieciI
else puts I7 ,ale dieciI
end
7 differen!a dellesempio precedente in questo caso abbiamo utili!!ato come condi!ioni delle
espressioni booleane, in alternati%a possibile utili!!are anche delle espressioni regolari, dei range
o delle classi rendendo il case uno strumento incredibilmente potente. Inoltre poich= case ritorna il
%alore dellultima espressione %alutata possibile assegnare ad una %ariabile il risultato del
costrutto>
value_n = case n
when n H =0: I7 M maggiore di dieciI
when n E =0: I7 M minore di dieciI
else I7 ,ale dieciI
end
W!ile e until
Con il costrutto while il ciclo %iene eseguito fino a quando la condi!ione si mantiene %era, ad
esempio>
lettera < IaI
while lettera E IgI
print lettera, I I
lettera*ne#t@
end
ci dar5 come output>
a b c d e f
il ciclo stato eseguito mentre la lettera ha assunto %alori minori, in ordine alfabetico, di 2g4. Fi
natura opposta until che esegue il ciclo finch= lespressione falsa, ad esempio>
lettera < IaI
until lettera H IgI
print lettera, I I
lettera*ne#t@
end
9output >
a b c d e f g
In questo caso il ciclo proseguito finch= la lettera non di%enuta maggiore di 2g4.
$or
9altro ciclo di note%ole interesse il classico for. Riprendendo lesempio precedente possiamo
scri%ere
for n in IaI**IgI
print n, I I
end
ottenendo
a b c d e f g
Il ciclo %iene eseguito una %olta per ogni %alore assunto da n. $el nostro esempio la %ariabile n
assume i %alori del range che ha per estremi le lettere 2a4 e 2g4. *ltre al range a%remmo potuto
indicare un array, o qualsiasi altro oggetto che risponde al metodo each , e la %ariabile a%rebbe
assunto tutti i %alori degli elementi dellarray, uno per ogni ciclo proprio come un iteratore.
)scire dai cicli
Concludiamo questa por!ione della guida illustrando i costrutti che permettono di modificare la
normale esecu!ione di un ciclo al %erificarsi di particolari condi!ioni.
brea#> termina immediatamente il ciclo e lesecu!ione del programma %iene ripresa dallistru!ione
immediatamente successi%a al ciclo. 7d esempio questo codice
while lettera E IgI
brea" if lettera << IdI
print lettera, I I
lettera*ne#t@
end
ci dar5 in output
a b c
il ciclo stato interrotto quando la lettera ha assunto il %alore 2d4.
Il costrutto ne;t in%ece salta alla fine del ciclo eseguendo una nuo%a itera!ione>
num < 0
while num E X
num Z< =
ne#t if num << W
print num, I I
end
In questo caso loutput
= > Y X
&uando num ha assunto %alore 0 il ne#t ha terminato litera!ione corrente, andando alla fine del
ciclo e saltando dunque listru!ione di stampa, e ha ini!iato litera!ione successi%a.
Ereditariet* singola
In questo e nel successi%o capitolo %edremo in maggiore dettaglio gli aspetti pi( interessanti, e utili,
della programma!ione ** in Ruby. Completeremo il discorso sulle classi ini!iato nel capitolo f
introducendo in questo capitolo lereditariet5 singola e nel prossimo lereditariet5 multipla.
Ricominciamo da do%e era%amo rimasti. 7lla fine del capitolo f a%e%amo due classi $arro.rmato e
$amion>
class $arro.rmato
attrreader :colpi, :carburante
def initialiGe (colpi, carburante)
Kcolpi < colpi
Kcarburante < carburante
end
def rifornimento (:uantita)
Kcarburante Z< :uantita
end
end
class $amion
attrreader :posti, :carburante
def initialiGe (posti, carburante)
Kposti < posti
Kcarburante < carburante
end
def rifornimento (:uantita)
Kcarburante Z< :uantita
end
end
7nche se scritte in modo corretto le nostre due classi non sono sicuramente scritte nel modo
migliore possibile, abbiamo infatti ignorato i principi base dellingegneria del soft"are. 8i nota
subito infatti che ci sono delle ripeti!ioni che possono essere eliminate utili!!ando lo strumento
dellereditariet5. &uindi un modo migliore di progettare le nostre classi pre%ede la crea!ione di una
superclasse che possiede gli attributi e i metodi comuni alle sottoclassi $arro.rmato e $amion. 7d
esempio creando la classe 0eicolo nel seguente modo>
class 0eicolo
attrreader :carburante
def initialiGe (carburante)
Kcarburante < carburante
end
def rifornimento (:uantita)
Kcarburante Z< :uantita
end
end
possiamo scri%ere le nostre classi di conseguen!a>
class $arro.rmato E 0eicolo
attrreader :colpi
def initialiGe (carburante, colpi)
super(carburante)
Kcolpi < colpi
end
end
class $arro.rmato E 0eicolo
attrreader :colpi
def initialiGe (carburante, colpi)
super(carburante)
Kcolpi < colpi
end
end
<ediamo cosa successo. Innan!itutto ora abbiamo una gerarchia di classi che %ede in cima la
classeApadre, o superclasse, 0eicolo che ha due classiAfiglie, o sottoclassi, $amion e $arro.rmato
che ne ereditano il metodo rifornimento e in parte il metodo initialiGe. In realt5 le nostre
sottoclassi speciali!!ano il metodo initialiGe di 0eicolo> per la %ariabile distan!a comune,
Kcarburante, %iene chiamato il metodo initialiGe della superclasse, attra%erso il costrutto
super, mentre le altre %ariabili sono gestite direttamente dalle sottoclassi. In definiti%a super non
fa altro che richiamare il metodo con lo stesso nome contenuto nella superclasse.
Ereditariet* multipla
Ruby, di per s=, non permette lereditariet5 multipla> ogni classe non pu6 a%ere pi( di una
superclasse. - possibile per6 aggirare questo 2problema4, che a detta di molti problema non ,
attra%erso lutili!!o dei moduli e il meccanismo del mixin.
*ltre al classico utili!!o per la crea!ione di namespace, i moduli possono essere utili!!ati per
implementare una sorta di ereditariet5 multipla. <ediamo innan!itutto cosa si intende per modulo e
come si definisce.
I moduli sono dei contenitori di metodi, costanti e classi e, alla stessa maniera delle classi, de%ono
a%ere un nome che ini!ia per lettera maiuscola. 8ono definiti dalla parola chia%e module un
esempio il seguente>
module 7et
class 5443
def 5443*getprint(uriorhost, path < nil, port < nil)
***
end
end
end
Ber poter accedere alle classi del modulo occorre importalo con listru!ione re:uire e poi fare
riferimento alle classi con il nome esteso. 7d esempio se si %uole utili!!are il metodo getprint
della classe @))B del modulo $et occorre scri%ere>
re:uire )netChttp)
7et::5443*getprint )www*google*com), )Cinde#*html)
9a crea!ione di un namespace permette sia di e%itare problemi con i nomi, sia di rendere il codice
pi( coerente e pulito. *ltre a ci6, come anticipato prima, possibile utili!!are i moduli in maniera
meno ortodossa ma molto efficace. Ber o%%iare alla mancan!a dellereditariet5 multipla basta
racchiudere in un modulo i metodi che %ogliamo 2far ereditare4 alla nostra classe e quindi
includerlo con listru!ione include. Fi conseguen!a possiamo utili!!are tutti i metodi del modulo
dallinterno della nostra classe come dei normali metodi che %engono mescolati, mixed in appunto,
a quelli definiti dalla classe e a quelli ereditati dalla superclasse.
Jn esempio ci chiarir5 tutto. Creiamo un semplice modulo con un solo metodo che non fa altro che
stampare una frase a %ideo>
module 1nutile
def hello
I+aluti da ?Sself*class*nameUI
end
end
class 4o"yo
include 1nutile
end
Istan!iando una nuo%a classe possiamo chiamare il metodo hello ereditato dal modulo ottenendo>
H t" < 4o"yo*new
H t"*hello
<H I+aluti da 4o"yoI
In questo modo possibile aggiungere alle classi una gran quantit5 di metodi sen!a nessuna fatica.
7d esempio possiamo dotare le nostre classi dei metodi di confronto includendo $omparable, o
anche aggiungere dei metodi di ricerca e ordinamento includendo &numerable e cos? %ia.
+pertura e chiusura di un file
Jna delle fun!ionalit5 pi( utili!!ata sicuramente la gestione dei file che in alcuni linguaggi una
delle esperien!e pi( frustranti per il programmatore inesperto fortunatamente non il caso di Ruby
che anche in questo frangente mantiene una grande immediate!!a e semplicit5.
7 questo punto il lettore a%r5 notato che qualsiasi argomento in Ruby non presenta mai unele%ata
difficolt5 ma tutto molto intuiti%o e di conseguen!a risulta anche molto naturale. Jna delle
descri!ioni pi( appropriate lette in giro dice che 2imparare Ruby non come scalare una montagna,
ma pi( come esplorare una pianura ad ogni argomento ne segue un altro, ma nessuno porta con se
grandi difficolt54.
)orniamo alle cose pratiche e %ediamo quali metodi offre la classe Eile per eseguire le opera!ioni
base sui file> apertura, chiusura, lettura e scrittura.
Apertura e c!iusura di un "ile
Come consueto per operare sul contenuto di un file occorre prima di tutto aprirlo. Il Ruby per
farlo mette a disposi!ione due metodi. Innan!itutto c il classico !ile*new, do%e !ile
o%%iamente la classe che si occupa dei file ed ha come superclasse I*, quindi si ha ad esempio>
miofile < !ile*new(Itest*t#tI, IrZI)
fatto questo tutte le opera!ioni %anno fatte sulloggetto miofile di tipo !ile. 7lla fine dopo
a%erlo opportunamente processato il file %a chiuso con>
miofile < !ile*close(Itest*t#tI, IrZI)
Eile.ne" pu6 prendere da uno a tre argomenti, il primo rappresenta il nome del file da aprire, il
secondo la modalit5 di apertura e il ter!o i permessi da associare al file. 9a modalit5 di apertura pu6
essere espressa sia come stringa sia come 2or4 di flag. )ra le principali flag, che sono costanti della
classe Eile, tro%iamo>
*44!5: apertura in modalit6 append
7R!*$: se il file da aprire non esiste viene creato
R25"8: apertura a sola lettura
R/R: apertura per lettura e scrittura
$R-57: apre il file e lo azzera se gi6 esiste
/R25"8: apertura a sola lettura
7nalogamente alle flag possibile usare le stringhe>
r: apertura a sola lettura
r9: apertura per lettura e scrittura dallinizio del file
0: apertura a sola scrittura, se il file non esiste ne viene creato uno nuovo, altrimenti viene
azzerato
09: apertura per lettura e scrittura, se il file non esiste ne viene creato uno nuovo, altrimenti
viene azzerato
a: apertura a sola scrittura dalla fine del file, se il file non esiste viene creato
a9: apertura per lettura e scrittura dalla fine del file, se il file non esiste viene creato
b: va aggiunto ad uno dei precedenti e permette la gestione in modalit6 binaria, esiste solo
per sistemi /indo0s.
I permessi, come ter!o argomento, %anno indicati, nei sistemi Jni;Ali#e, nella classica forma
*"nerA'roupA*ther.
*ltre alla modalit5 classica di apertura, con la coppia ne"Kclose, il Ruby permette di aprire un file
anche con il metodo open. 7 differen!a di new a open pu6 essere associato un blocco al quale
%iene passato il file appena aperto come parametro>
!ile*open(Itest*t#tI, IrZI) do TmiofileT
***
end
Jtili!!ando open non c pi( bisogno di chiamare al termine delle opera!ioni close poich= il file
%iene chiuso automaticamente alluscita dal blocco open pu6 anche essere in%ocato sen!a blocco e
in tal caso solo un sinonimo di new e %algono per esso tutte le considera!ioni fatte in preceden!a.
Lettura e scrittura
Fopo a%erlo aperto le opera!ioni base sui file sono la lettura e la scrittura. Ber leggere un file una
linea alla %olta si pu6 utili!!are il metodo gets ereditato da I*>
while linea < miofile*gets
puts linea
end
in questo modo con un ciclo while non facciamo altro che stampare a %ideo tutte le righe del file.
In alternati%a possibile usare anche gli iteratori che insieme a open con i blocchi rendono le
opera!ioni di lettura molto age%oli. )ra gli iteratori tro%iamo>
each,byte che chiama il blocco per ogni byte
each,line, e il suo sinonimo each, chiamano il blocco per ogni riga
7d esempio supponendo che il nostro file test.txt abbia il seguente contenuto>
0ento in,ernale
Un monaco scinto
$ammina nel bosco
possiamo leggerne un carattere alla %olta con eachbyte>
!ile*open(Itest*t#tI) do TfT
f*eachbyte STcT print c*chr, I IU
end
in questo modo trasformiamo il byte letto, un !i#num, in carattere con il metodo chr e poi lo
stampiamo seguito da uno spa!io. 9output sar5>
0 e n t o i n , e r n a l e
U n m o n a c o s c i n t o
$ a m m i n a n e l b o s c o
'li iteratori each e eachline, come detto, permettono in%ece di iterare su ogni linea del file. Jn
esempio >
!ile*open(Itest*t#tI) do TfT
f*each STlT puts I?Sf*linenoU ?SlUIU
end
do%e lineno un metodo della classe I* che restituisce il numero di linea corrente. 9output sar5
dunque>
= 0ento in,ernale
> Un monaco scinto
W $ammina nel bosco
Infine un altro iteratore, che allo stesso tempo un altro modo per aprire un file, foreach che
quando in%ocato apre il file passatogli come argomento, chiama il blocco per ogni linea e alla fine
chiude il file automaticamente>
1-*foreach(Itest*t#tI) STlineaT puts lineaU
Ber scri%ere su di un file si utili!!a il metodo write che prende come argomento la stringa da
scri%ere sul file>
!ile*open Itest*t#tI, IwI do TmiofileT
miofile*write I$iao fileI
end
write restituisce il numero di byte scritti. In alternati%a si pu6 utili!!are anche loperatore EE o il
metodo puts. 9esempio precedente di%enta>
!ile*open Itest*t#tI, IwI do TmiofileT
miofile EE I$iao fileI
end
oppure
!ile*open Itest*t#tI, IwI do TmiofileT
miofile*puts I$iao fileI
end
)tili metodi e gestione directory
Concludiamo con una carrellata dei principali metodi utili!!abili sui file>
atime, ctime e mtime restituiscono rispettivamente la data di ultimo accesso, di creazione e
di modifica
chmod e cho0n modificano i permessi e il proprietario
lstat restituisce delle informazioni sul file
rename rinomina il file
delete e unlin: cancellano il file
size restituisce le dimensioni in byte
read restituisce il contenuto del file in una unica stringa
readchar legge un carattere dal file
readline legge una linea dal file
readlines restituisce un array avente per elementi le linee del file
file < !ile*new(Itest*t#tI)
file*readlines <H [I0ento in,ernalenI, IUn monaco scintonI, I$ammina nel
bosconI]
poi ci sono i metodi interrogati%i>
e.ist; restituisce true se il file passato come argomento esiste
e.ecutable; restituisce true se il file # eseguibile
readable; restituisce true se il file # leggibile
0ritable; restituisce true se il file # scrivibile
file; restituisce true se # un file regolare, ovvero se non # un soc:et, una directory, etc.
o0ned; restituisce true se luser I del processo # lo stesso del file
Le directory
Brima di concludere questo capitolo, per complete!!a, diamo uno sguardo anche alle directory. 9a
classe per la gestione delle directory %ir e anche in questa classe abbiamo i metodi new, open e
close con lo stesso significato %isto per i file. 7d esempio creiamo, apriamo e chiudiamo una
directory in questo modo>
%ir*m"dir(ItestI)
testdir < %ir*new(ItestI)
testdir*close
oppure con open, sen!a bisogno di chiamare close alla fine delle opera!ioni>
%ir*open(ItestI) do TdT
***
end
Fo%e %ir*m"dir crea una nuo%a directory, possibile passargli come secondo argomento anche i
relati%i permessi. Ber il resto rimando alla documenta!ione ufficiale per un elenco completo di tutti i
metodi.
Le espressioni regolari
9e espressioni regolari sono uno strumento fondamentale per la gestione del testo, e uno dei
linguaggi che ha fatto di questo strumento un punto di for!a sicuramente il Berl. Il Ruby, che nelle
idee di 3at! nasce come suo naturale erede, non pote%a non a%ere un supporto alle espressioni
regolari altrettanto potente.
+re%emente, rimandando a testi appositi una tratta!ione pi( approfondita, possiamo dire che le
espressioni regolari %engono utili!!ate per controllare se una stringa %erifica un certo schema
CpatternD. * in altre parole, le espressioni regolari, forniscono dei modelli per ricercare allinterno di
un testo non solo utili!!ando espressioni letterali ma anche particolari identificatori che
rappresentano delle determinate classi di caratteri.
In Ruby sono oggetti della classe /ege#p che possono essere creati, come gli 7rray e gli @ash, in
di%ersi modi. 8i pu6 utili!!are il metodo new di /ege#p>
e#pr < /ege#p*new()))
passando come argomento lespressione regolare %era e propria, oppure racchiudendola tra due K
C]slashD>
e#pr < CC
o ancora utili!!ando Fr>
e#pr < FrSU
Jna %olta creata la nostra espressione regolare possiamo confrontarla con qualsiasi stringa
utili!!ando il metodo match della classe /ege#p oppure loperatore <B e il suo negato @B. 7d
esempio>
H er < /ege#p*new()swZ))
<H CswZC
H stringa < I$iao mondoI
<H I$iao mondoI
H stringa <B er
<H Y
H $]m
<H I mondoI
H $`
<H I$iaoI
<B restituisce la posi!ione del primo carattere che %erifica lespressione regolare mentre le %ariabili
speciali $] e $` rappresentano rispetti%amente la parte di stringa che %erifica il pattern e la parte che
non lo %erifica.
Come gi5 detto, allinterno di una espressione regolare oltre ai normali caratteri possibile usare
delle sequen!e che rappresentano delle determinate classi, in )abella. c un elenco completo. In
alternati%a possibile creare delle classi racchiudendo i caratteri tra parentesi quadre, ad esempio
[.-aa-G] sta a indicare tutte le lettere dalla a alla ! sia maiuscole che minuscole.
)abella .> classi di caratteri
. un carattere qualsiasi
" lettera o numero, come ^0A/7AgaA!_
: il contrario di ", ne lettera ne cifra
s spa!io Cspa!io %ero e proprio, tabula!ione e carattere di fine rigaD, come ^tnrf_
8 carattere non spa!io
d cifra numerica, come ^0A/_
F il contrario di d, carattere non numerico
b bac#space se si tro%a in una specifica di inter%allo
b limite di parola CboundD
+ non limite di parola
*ltre ai caratteri in una espressione regolare possibile anche utili!!are due particolari elementi, b
C]accento circonflessoD e $ C]dollaroD, che indicano una precisa posi!ione del testo cercato. b %a
usato se i caratteri cercati si de%ono tro%are allini!io del testo, $ se si de%ono tro%are alla fine. Ci
sono quindi i simboli quantificati%i>
)abella 2> i simboli di quantit5
X !ero o pi( ripeti!ioni del carattere precedente
G una o pi( ripeti!ioni del carattere precedente
cm,nd almeno m e massimo n ripeti!ioni del carattere precedente
h al massimo una ripeti!ione del precedente lo stesso che c0,.d
7bbiamo poi T C]pipeD che rappresenta il meccanismo dellalternan!a che permette di definire pi(
alternati%e. 7d esempio ChttpTftpTsmtpC permette di tro%are una delle corrisponden!e indicate
nellespressione. Infine, come consueto, possibile catturare una parte della stringa %erificata in
modo da utili!!arla sia allinterno del pattern stesso, riferendoci ad essa con =, > e cos? %ia, sia
allesterno utili!!ando le %ariabili speciali $=, $> ecc. 7d esempio %olendo catturare la parola
2mondo4 dellesempio precedente dobbiamo scri%ere>
H er < /ege#p*new()s(wZ)))
<H Cs(wZ)C
H stringa < I$iao mondoI
<H I$iao mondoI
H stringa <B er
<H Y
H $=
<H ImondoI
Le espressioni regolari e la classe -tring
$el capitolo .2 dedicato alle stringhe abbiamo gi5 incontrato delle espressioni regolari che ora
possiamo comprendere meglio, ri%ediamole. Ber accedere a delle sottostringhe si pu6 scri%ere
H str < I$iao mondoI
<H I$iao mondoI
H str[CwZsC]
<H I$iao I
8inonimo di ^_ il metodo slice e il metodo slice@>
H str*slice(CwZsC)
<H I$iao I
7llo stesso modo si utili!!ano con inde# che restituisce lindice della prima occorren!a della
sottostringa espressa dal pattern>
H str*inde#(C[aeiou]C)
<H =
analogo il comportamento di rinde# che, a differen!a di inde#, restituisce lultima occorren!a
della sottostringa che %erifica il pattern>
H str*rinde#(C[aeiou]C)
<H [
Bossiamo usare le espressioni regolari anche come argomento dei metodi sub e gsub>
H str*gsub(C([aeiou])C, )(=)) )
<H I$(i)(a)(o) m(o)nd(o)I
H str*gsub(Cs(wZ)C)STcT c*upcaseU
<H I$iao L-7%-I
7nche split pu6 essere utili!!ato passando come argomento unespressione regolare>
H str*split(CsC)
<H [I$iaoI, ImondoI]
Interessante infine lutili!!o delle rege#p con scan che itera attra%erso la stringa e inserisce tutti
i risultati che %erificano il pattern allinterno di un array>
H str*scan(CwZC)
<H [I$iaoI, ImondoI]
Fa questi esempi lampante la note%ole %ersatilit5 che le espressioni regolari aggiungono ai metodi
della classe +tring.
Le eccezioni
Concludiamo con questo e con il successi%o capitolo la prima parte della nostra panoramica del
Ruby trattando la gestione delle ecce!ioni, dal prossimo ci occuperemo di questioni accessorie al
linguaggio %ero e proprio.
Come tutti i linguaggi moderni, anche il Ruby, possiede il meccanismo delle ecce!ioni,
fondamentale nella gestione degli errori. Jnecce!ione %a solle%ata utili!!ando il metodo raise del
modulo Hernel. 9a sintassi completa pre%ede tre argomenti>
raise(e#ception [, string [, array]])
Il primo argomento il nome di una classe della gerarchia &#ception C%edi lista pi( a%antiD e
rappresenta il tipo di ecce!ione da solle%are. Il secondo argomento un messaggio che %err5
associato allecce!ione, mentre il ter!o un array con il callbac# dellecce!ione. Chiamato sen!a
nessun argomento raise solle%er5 un ecce!ione di tipo /untime&rror, oppure se definita
lecce!ione contenuta in $@. 7d esempio>
raise I&rrore nell)apertura del fileI
raise .rgument&rror, I4ipo di argomento non gestitoI
raise .rgument&rror, I4ipo di argomento non gestitoI, caller
9a gerarchia delle ecce!ioni in Ruby
&#ception
7oLemory&rror
+cript&rror
2oad&rror
7ot1mplemented&rror
+ynta#&rror
+ignal&#ception
1nterrupt
+tandard&rror
.rgument&rror
1-&rror
&-!&rror
1nde#&rror
2ocal8ump&rror
7ame&rror
7oLethod&rror
/ange&rror
!loat%omain&rror
/ege#p&rror
/untime&rror
+ecurity&rror
+ystem$all&rror
+ystem+tac"&rror
4hread&rror
4ype&rror
aero%i,ision&rror
+ystem&#it
fatal
La gestione degli errori
Fopo a%er %isto come si solle%ano le ecce!ioni diamo uno sguardo alla loro gestione attra%erso
rescue ed ensure. 8upponiamo di a%er scritto una applica!ione che si comporta in modo di%erso a
seconda che esista o meno una determinata libreria. <ogliamo dunque intercettare une%entuale
ecce!ione 2oad&rror e comportarci di conseguen!a. Ber catturare le ecce!ioni scri%iamo il tutto in
un blocco beginKend, ad esempio>
begin
re:uire )gmailer)
(L.12+U33-/4&% < true
rescue 2oad&rror
(L.12+U33-/4&% < false
end
in questo modo impostiamo la costante (L.12+U33-/4&% in base alla disponibilit5 della libreria
gmailer. - possibile anche indicare pi( clausole rescue allinterno dello stesso blocco, mentre se
non si indica nessun argomento rescue intercetter5 tutti gli errori che discendono da
+tandard&rror. Ber recuperare il %alore dellecce!ione %a utili!!ata questa sintassi>
begin
re:uire )gmailer)
(L.12+U33-/4&% < true
rescue 2oad&rror <H error
puts I2)errore M: ?SerrorUI
(L.12+U33-/4&% < false
end
e in caso di ecce!ione 2oad&rror %edremo sullo schermo la scritta 29errore > no such file to load
i gmailer4. 7llinterno del corpo di rescue si pu6 inserire unistru!ione retry con la fun!ione di
rieseguire il blocco dallini!io, o%%iamente prima di retry %anno eseguite delle istru!ioni atte a
risol%ere il problema riscontrato. Infine c la clausola ensure utile quando si de%ono eseguire
delle opera!ioni alluscita da un blocco beginKend. Jn classico esempio quello della gestione dei
file>
file < !ile*open(Itest*t#tI)
begin
? operaGioni ,arie sul file
rescue
? gestione degli errori
ensure
file*close unless file*nilP
end
$el blocco principale %engono eseguite le normali opera!ioni sul file aperto, poi c il blocco
rescue per la gestione degli errori e infine nel blocco ensure ci sono le istru!ioni per chiudere il
file. In questo modo siamo sicuri che alluscita dal blocco il file %err5 chiuso.
*ltre che allinterno dei blocchi beginKend, possibile gestire le ecce!ioni anche allinterno dei
normali metodi, il cui corpo implicitamente un blocco beginKend>
def nomemetodo
? istruGioni ,arie
rescue
? gestione degli errori
end

Potrebbero piacerti anche