Ruby in 25 minuti Una rapida introduzione al maggico mondo di Ruby - di Marcello Missiroli ([email protected]) - with a little big help from Peter Marklund (http://marklunds.com ) and Jan Elis
Ruby in 25 minuti
Una rapida introduzione al maggico mondo di Ruby- di Marcello Missiroli ([email protected])
- with a little big help from Peter Marklund (http://marklunds.com) and Jan Elis
Chi sono?
•Insegno Informatica e sistemi da... troppo tempo.
•Al Corni dall' AS 2007/2008
•Gestisco il sito di Moodle della scuola
Cosa vedremo?In questa rapida esposizione vedremo cos'è Ruby, i suoi punti di forza e perché dovreste impararne tutti un po' prima di andare a lavorare nel campo.
In particolare mi concentrerò un ciò che rende distingue Ruby dagli altri linguaggi di programmazione in modo radicale
IntroduzioneParte 1
Tappe fondamentali dei
linguaggi• Anni '40: Linguaggio macchina codificato, Assembly
• Anni '50: FORTRAN / COBOL (Compilazione/ General Purpose)
• Anni '60: BASIC / LOGO (Linguaggi interpretati)
• Anni '70: PASCAL / C (Controllo sintattico/Efficienza)
• Anni '80: Smalltalk/C++(Object Oriented programming)
• Anni '90: Java/Javascript e Perl (Bytecode e garbage
collection/Scripting)
Diffusione dei linguaggi
• 1° posto: C
• 2° Posto: Java
• 3° Posto: Objective-C
• 4° Posto: C++
• 5° Posto: C#
• 6° Posto: (Visual) Basic
Fonte: Tiobe http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Mumble, mumble, forse c'è spazio per
un linguaggio con concettipiù moderni, no?
Eccovi Ruby
• Generico, interpretato, “reflective” , con garbage collection
• Ottimizzato per la produttività e felicità
• Conciso ma leggibile con sintassi chiara
• Puro Object oriented – TUTTO è un oggetto (anche le
primitive)
• Programmazione funzionale
• Tipi di dati dinamici / “Duck Typing”
• Open Source (GPL e “The Ruby License”)
Ruby e la felicitàBill Venners: “Per cui, di base Ruby aiuta ad apprezzare la vita permettendo di svolgere il suo lavoro più velocemente e in modo più divertente”
Yukihiro Matsumoto: “Sì, mi aiuta. Non so se funzionerà per lei, ma spero di si”
Caposaldi Ruby
Pragmaticità
Aderenza alle convenzioni
Leggibilità
Bellezza (!)
Struttura ed Esecuzione
Parte 2
Istruzioni
Le istruzioni sono separate da A CAPO
Potete, opzionalmente, separarle con “;”
Esecuzione• Linguaggio interpretato linea per linea
• Utilizzabile come script in modo simile a bash o come linguaggio server-side
• Tutto accade in runtime. Pertanto, tutto può essere cambiato.
• Non esiste il 'main'. Si esegue come uno script o interattivamente con il comando irb
• Require permette di caricare codice scritto da noi o da altri (le cosiddette 'gemme')
• Le gemme sono scaricabili direttamente via internet (con un metodo simile a CPAN)
Nomi degli identificatori
LaMiaClasse, IlModulo
LA_MIA_COSTANTE = 3.14
il_mio_metodo
variabile_locale = 3.14
@variabile_istanziata
@@variabile_di_classe
$variabile_globale
“CAMEL STYLE”
“SNAKE STYLE”
Suffissi
metodo_pericoloso_o_modificante!
metodo_che_risponde_a_domande?
metodo_setter=
Booleani
• Le “costanti” booleane sono false e true. In gli unici valori che sono “falsi” in senso booleano sono: false, nil
• Se venite dal C e derivati, attenti: zero (0) e la stringa vuota (“”) risultano true!
Source code: truth.rb
Booleani
• Le “costanti” booleane sono false e true. In gli unici valori che sono “falsi” in senso booleano sono: false, nil
• Se venite dal C e derivati, attenti: zero (0) e la stringa vuota (“”) risultano true!
Source code: truth.rb
Tipi di datoParte 3
Numeric
• Tutti i numeri in Ruby sono oggetti e fanno parte della classe di base Numeric, dotata di molte sottoclassi. Comprende anche “Infinity” e “Nan”
• Fixnum → 6356Float → 6,466 BigDecimal → 628363263629,389893Complex → (2+3i) Rational → (2/3)
Source code: numeric.rb
Stringhe
• Le stringhe sono codificate in UTF-8 e modificabili
• Oltre agli operatori più comuni, sono previsti anche : +, <<, []
• Possono comprendere al loro interno variabili con #{}:w=3; c=”Il valore è #{w}”
• Metodi interessanti: size, each_char, each_line, empty?, gsub, strip, upcase
Source code: string.rb
Array
• Gli Array sono a dimensione variabile, senza tipi
• Molti operatori in comune con le stringhe: +, <<, []
• Di tipo “Enumerabile”, per cui forniti di metodi come each, select, map, inject .
Source code: array.rb
Hash
• Gli Hash sono array associativi (stile PHP) con chiave unica.
• Possono essere usati come parametri
• Sono enumerabili
Source code: hash.rb
Simboli
• I simboli sono stringhe immutabili (stile Java)
• Sono una stringa o un identificatore preceduto da due punti: :il_mio_simbolo
• Usati come chiavi per le hash e come nome dei metodi
• Più efficienti delle stringhe
Source code: symbol.rb
Range
• Un range rappresenta tutti i valoro compresi tra quelli indicati: 1..100, 2.67...300.676, 'a'...'z'
• Se ci sono due punti, il valore finale è escluso; con tre punti è incluso
• Metodi intessanti: each, step, include?, member?
Source code: range.rb
Regexp
• Le espressioni regolari sono delimitate da slash:: /(?<mese>\d{1,2})\/(?<giorno>\d{1,2})\/(?<anno>\d{4})/
• Per controllare un'espressione si usa l'operatore =~ Stringa#match
• Si possono effettuare sostituzioni tramite String#gsub
• Molto potente e utile (specie per le applicazioni web)
Source code: regexp.rb
nil
• nil indica l'assenza di un oggetto. E' il valore che ha un oggetto non instanziato, e di solito si testa per prevenire errori
• Ossimoricamente, anche nil è un oggetto, accessibile da tutti
10 secondi....
• ([ 1, 2, 3 ] + [ 3, 4, 5, 6 ] - [ 1 ]).uniq =>
([] << 1 << 2 << “dietro” ) .unshift(“davanti”) =>
[1,2,3,4,5,6].map { |x| x+1 } =>
...per capire cosa fa ogni riga di codice
10 secondi....
• ([ 1, 2, 3 ] + [ 3, 4, 5, 6 ] - [ 1 ]).uniq => [2, 3, 4, 5, 6]
([] << 1 << 2 << “dietro” ) .unshift(“davanti”) => ["davanti", 1, 2, "dietro"]
[1,2,3,4,5,6].map { |x| x+1 } => [2, 3, 4, 5, 6, 7]
...per capire cosa fa ogni riga di codice
Strutture di controllo
Parte 4
Condizionali
• Non manca il classico: if, elsif, else, end
• Esiste anche il famigerato operatore ternario (“(i>0)?4:8”) e la struttura case...when...else. Si noti la sinteticità! manufacturer = case car when "Focus" then "Ford" when "Navigator" then "Lincoln" when "520i" then "BMW" when "Tundra" then "Nissan" else "Unknown"end
Source code: conditionals.rb
Cicli
• Esistono i classici while,until ma il metodo considerato “giusto” è quello di utilizzare il metodo each che si applica a qualsiasi oggetto Enumerable.
a = [ "a", "b", "c" ]
a.each {|x| print x, " -- " }
Source code: loops.rb
Cicli(2)
• for si usa applicato a un range. for i in 1..8 { puts i}
• Si possono utilizzare anche metodi applicabili a numeri quali times, upto, dowto, step che rendono il ciclo molto elegante
5.times { |i| puts i }1.upto(5) { |i| puts i }
Source code: loops.rb
Eccezioni
• Molto simili alla gestione delle eccezioni in altri linguggi: si lanciano con raise e si catturano con rescue
• ensure indica un blocco che deve essere sempre eseguito, retry ri-esegue il codice con errore.
• Ruby ha una gerarchia di eccezioni predefinite basate su Exception, ma potete definirne di nuove
Source code: exceptions.rb
Bash? Chi era costui?
# converti testo da Unix a(LF) a DOS (CR/LF)$ ruby -ne 'BEGIN{$\="\r\n"}; print $_.chomp' < file.txt
# stampa righe di 65 caratteri o più$ ruby -pe 'next unless $_.chomp.length >= 65' < file.txt$ ruby -lpe 'next unless $_.length >= 65' < file.txt
# Stampa il file rimuovendo righe duplicate e consecutive$ ruby -ne 'puts $_ unless $_ == @prev; @prev = $_' < file.txt
http://reference.jumpingmonkey.org/programming_languages/ruby/ruby-one-liners.html
Classi e OggettiParte 5
Definire e istanziare
• class definisce una classe
• def definisce un metodo
• initialize è il costruttore
• Gli attributi / variabili d'istanza hanno il prefisso @
• I metodi si richiamano con la notazione oggetto.metodo.
• Le parentesi sono opzionali (!)
• Esistono le classi di visibiltà standard (public, private, protected)
Source code: person.rb
Esempio
class Counter def initialize @value=0 end def inc @value=@value+1 end def value? @value endend
c=Counter.newputs c.value?c.incputs c.value?
Getter e Setter
• Le variabili d'istanza sono SEMPRE private e bisogna utilizzare getter e setter
• Per i setter, è possibile utilizzare metodi il cui nome termina per “=” e utilizzare il metodo con sintassi normale: oggetto.attributo = valore
Source code: getter_setter.rb
attr_accessor
La macro attr_accessor genera in modo automatico getter and setter per le variabili indicate.
class Esempio attr_accessor :numero end
x=Exempio.new; x.numero=6; puts x.numero
Source code: attr_accessor.rb
Ereditarietà
• Per definire classi derivate, si usa la sintassiclass ClasseFiglia < ClasseBase
• Per richiamare metodi della classe base si usa super
• Per accedere all'oggetto corrente si usa self
Source code: programmer.rb
Mixins
• In Ruby l'ereditarietà multipla si realizza con i Moduli
• I moduli sono un'insiemi di metodi costanti e variabili che possono essere “aggiunti” a una classe
• Simili, ma più potenti, delle Interfaces di Java.
• Non possono essere instanziate
Source code: mixins.rb
Comparable
• Se si include il modulo Comparable, si ottengono i seguenti metodi di confronto: <, <=, ==, =>, >
• Si può utilizzare l'operatore <=> (operatore 'astronave') per confrontare due oggetti. Il risultato deve essere -1, 0, o 1 (stile strcmp del C)
Source code: comparable.rb
Parametri
• I parametri possono avere valori di default
• Possono avere un numero variabile di parametri
• Se il parametro inizia con un asterisco, indica che è un
array di 0 o più elementi
Operatori
• Molti operatori sono in realtà metodi e possono essere “overridati”
• 2 + 2 è equivalente to 2.+(2)
Source code: method_operators.rb
Rapidi cenni a cose interessanti
Parte 6
Blocchi, Proc e Lambda
• Si possono passare blocchi di codice (in gergo, closure) come ultimo parametro di un metodo. Il codice viene richiamato con yield
• In modo simile, esitono gli oggetti Proc, che sono direttamente eseguibili e Lambdas.
• Permettono alcuni aspetti della programmazione funzionale
Source code: blocks.rb
Introspezione
• Ruby è dotato di molti metodi per controllare la classe stessa. Per esempio: class, superclass, ancestors, instance_of?, is_a?, methods, instance_methods
• Si può controllare se un oggetto implementa un dato metodo con respond_to?
Source code: introspection.rb
Metodi dinamici
• Se chiama un metodo in esistente si ottiene un'eccezione. Ma se aggiungete il metodo method_missing si può intercettare l'errore e fare cose intelligenti (per esempio simulare dinamicamente il nome di un metodo – molto usato in Rails)
• Si può usare send per richiamare un metodo tramite una stringa o simbolo!
Source code: method_missing_and_send.rb
Classi aperte
• In Ruby TUTTE le classi sono dinamiche e possono essere modificate in runtime
• Con l'esempio a lato, posso utilizzare questa espressione:
puts 4.fattoriale
Source code: open_classes.rb
class Integer < Numericdef fattoriale my_i = self.to_i if my_i <= 0 result = 0 else result = 1 my_i.downto(2) do |n| result = result * n end end result endend
Standard Library
DRb (distributed object system)net/ftp, net/http, net/imap, net/pop, net/smtp, net/telnet, open-uri, opensslBase64, Digest (HMAC, SHA256, and SHA384)optparse ìPathname, FileUtilsLoggerCSVREXML (libreria XML in Ruby puro, Nokogiri in Rails)YAMLThread, Fiber
Lista completa: http://www.ruby-doc.org/stdlib
Testing
• La metodologia di Testing (TDD) è particolarmente diffusa nella comunità Ruby Unit tests typically test at the class or method level
• Test::Unit è il metodo di Test più diffuso
• RSpec e Cucumber are librerie di test molto più potenti che permettono di scrivere test utilizzando (quasi) il linguaggio umano
Source code: unit_testing.rb
Documentazione
• RDoc library usa il codice sorgente per per generare la documentazione in HTML
• I commenti RDoc precedono classi, moduli e metodi la loro descrizione
• Simile a JavaDoc, ma meno intrusivo
Source code: rdoc.rb
def bellezza?
armoniaconcisione
flessibilià
semplicità
conservativismo
• E' difficile definire un codice “bello” o “poetico” se non in termini di armonia tra le sue componenti
• Programmare (e leggere il codice) deve essere bello e divertente
• Happy hacking!
Esempio 1class Array
def qsort
return self if self.size <= 1
left, right = [], []
pivot = self.shift
self.each do |ele|
ele <= pivot ? left << ele : right << ele
end
left.qsort + [pivot] + right.qsort
end
end
Uso:
[0,2,3,-4,7.-12].qsort
Esempio 2 class User < ActiveRecord::Base
attr_accessible :description, :email, :location, :name, :nick, :password, :password_confirmation
has_many :groups, dependent: :destroy
has_many :interests, dependent: :destroy
valid_email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, :presence => true,
:format => { with: valid_email_regex },
:uniqueness => { case_sensitive: false }
validates :name, presence: true, length: { maximum: 50 }
validates :password, length: { minimum: 6, maximum:15 }
validates_confirmation_of :password
validates_presence_of :password_confirmation, :if => :password_changed?
Esempio 3# language: it
Scenario: Aggiugere un nuovo utente
Dato mi trovo nella pagina di registrazione
Quando inserisco in "user_name" "Paperino"
E inserisco in "user_email" "[email protected]"
E inserisco in "user_password" "12345678"
E inserisco in "user_password_confirmation" "12345678"
Quando premo "Crea utente"
Allora dovrei essere nella home page
E dovrei vedere "Utente Paperino creato"
Appendice
•Per la serie: potevamo stupirvi con gli effetti speciali....
Una web app in meno di
minuti con Rails
22Look, Ma, no GUI! Just 5 LOC!
E' finita!
GRAZIE PER L'ATTENZIONE
Sitologia
• tryruby.org (principianti)
• rubymonk.com (principianti/intermedi)
• rubykoans.com (intermedi/avanzati)
LicenzaQuesto lavoro è protetto dalla licenza Creative Commons BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/deed.it)
Il lavoro originale di Peter Marklund usa la Creative Commons BY 3.0 (si trova su https://github.com/peter/ruby_basic )