Diapositivas correspondientes a la parte de la plataforma de desarrollo Ruby del curso de extensión universitaria "Desarrollo Web Avanzado", celebrado en la Escuela Universitaria de Ingeniería Informática de Oviedo
3. Ruby es un lenguaje...
Productivo
Dinámico
Orientado a objetos
Funcional
4. Ruby es Orientado a Objetos
-199.abs # 199
"ruby no está nada mal".length # 21
["G", "A", "T", "T", "A", "C", "A"].uniq.sort.join # "ACGT"
{:hielo=>"frío", :fuego=>"caliente"}.values # [“frío”,”caliente”]
No existen tipos primitivos.Todos los literales son objetos
El estado y comportamiento de los objetos se define a través
de clases
class Punto
attr_accessor :x,:y
def initialize(x,y)
@x=x
@y=y
end
def to_s
"Punto (#{@x},#{@y})"
end
end
origen=Punto.new(0,0)
origen.x+=1 #igual que origen.x=origen.x+1
puts origen #=> Punto (1,0)
ruby_oo.rb
5. Ruby es dinámico
No hay declaraciones explícitas de tipos
El tipo de los objetos viene determinado por su conjunto de
métodos y no por la clase a la que pertenezca.*
*Duck typing: a way of thinking about ruby programming -
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/78502
lista=[1,2,3,"Hola"] #ruby
List<? extends Object> lista= Arrays.asList(1,2,"Hola"); //java
duck_typing.rb
6. Ruby es funcional
En ruby todas las funciones pueden recibir un bloque, que es
una función anónima.
anonymous.java
[1,2,3].map{ |x| x**2 } #[1, 4, 9]
10.downto(1){ |x| puts x } # imprime los números del 10 al 1
Los bloques permiten parametrizar el comportamiento de la
función que la recibe (patrón Strategy)
%w(ruby es ruby, no c++).sort do |una_palabra,otra_palabra|
una_palabra.size - otra_palabra.size
end #["no", "es", "c++", "ruby", "ruby,"]
blocks.rb
7. Ruby es funcional
block_given? permite conocer si se ha pasado un bloque
a una función y yield permite invocarlo.
blocks.rb
class Array
def filtra
filtrados=[]
if block_given?
each do |elemento|
filtrados << elemento if yield elemento
end
filtrados
else
self
end
end
end
[1,2,3,4].filtra do
|elemento| elemento % 2 == 0
end
#=> [2,4]
colores=%w{rojo amarillo azul verde}
%w{el cielo es azul}.filtra do
|palabra| colores.member? palabra
end
#=>["azul"]
8. Ruby es un lenguaje productivo
Ruby es reflectivo. El código puede ser observado y modificado
en tiempo de ejecución ➔ El propio programa puede crear
código por nosotros (metaprogramación)
reflection.rb
El carácter dinámico y funcional del lenguaje, unido a una API
completa, hacen que el código sea más compacto y legible.
9. Core API (at a glance)
Cadenas y Símbolos
Números
Expresiones regulares
http://www.ruby-doc.org/core/
Rangos, Listas y Diccionarios
11. Cadenas (String)
ranges.rb
http://ruby-doc.org/core/classes/String.html
A diferencia de la mayoría de los lenguajes de alto nivel, son
objetos mutables
# Comillas simples: no se evaluarán las expresiones #{}
'una cadena entre comillas #{"simples".upcase}'
#=> una cadena entre comillas #{"simples".upcase}
# Comillas dobles sí se evaluarán las expresiones #{}
"una cadena entre comillas #{"dobles".upcase}"
#=> una cadena entre comillas DOBLES
#Varias líneas
s=<<END
Hola esto
es un documento
de texto
en varias lineas
END
#Troceado de palabras
%w{Hola mundo} #=> ["Hola", "mundo"]
"Hip,"*2 + "hurray!"
#=> Hip,Hip,hurray
"Ruby, no es ... ".length
# => 16
"Ruby, no es... ".split(/s*/)
# => ["R", "u", "b", "y", ",", "n", "o",
"e", "s", ".", ".", "."]
"Ruby, no es python".scan(/ruby|python/i)
# => ["Ruby", "python"]
"Ruby, no es python".include?("python")
#=>true
"Ruby, no es python".end_with?("python")
#=>true
Ruby, no es python".gsub(/Ruby, no/i,
"Python sí ") # => Python sí es python
✍
12. Símbolos (Symbol)
http://ruby-doc.org/core/classes/Symbol.html
Representan símbolos en la tabla símbolos del intérprete. Sólo
existe una única instancia de cada símbolo durante la ejecución de
un programa. a=:hola
b=:hola
a.equal? b # => true
a==b # => true
a= "hola"
b= "hola"
a.equal? b # => false
a==b # => true
Se usan por eficiencia para representar cadenas constantes o
nombres. A diferencia de los strings, cada vez que se usa no se
crea una nueva instancia.
link_to("View Article", :controller => "articles", :action => "show", :method
=>:get)
"Hola".method(:to_s).call
class Persona
attr_reader :nobre,:edad
end
✍
13. Rangos (Range)
Representan conjuntos de valores (no sólo numéricos).
Sólo almacenan los extremos
1..10 #Números del 1 al 10
1...10 #Números el 1 al 9 (extremo superior no incluido)
'A'..'Z' #Letras de la A a la Z
require 'date'
hoy=Date.today
hace_un_mes = hoy << 1 # Date#<<(n) Resta n meses a la fecha
hace_un_mes...hoy # => 2010-02-20...2010-03-20
Métodos útiles
digits=0..9
digits.include? 5 # => true
digits.min # => 0
digits.max # => 9
digits.minmax # => [0,9]
digits.reject {|digit| digit % 2 == 0} # => [1, 3, 5, 7, 9]
digits.select {|digit| digit < 5 } # => [0, 1, 2, 3, 4]
digits.each {|digit| print digit," "} # 0 1 2 3 4 5 6 7 8 9
digits.to_a #=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
http://ruby-doc.org/core/classes/Range.html
✍
18. if / unless
http://ruby-doc.org/core/classes/Hash.html
✍
Toda expresión evalúa a true, excepto false y nil
#Asignar sólo si nombre tiene un valor
def name=(name)
@name = name if name
end
def name=(name)
@name = name unless name.nil?
end
if [expresion] #leer "si"
"acción si expresión evalua a true"
elsif [expresion2]
"acción si expresion2 se evalua a true"
else
"acción si no si expresion y expresion 2 son falsas"
end
unless [expresion] #leer "a menos que"
"accion si expresion evalua a false"
else
"acción si expresión se evalua a true"
end
19. case - when
score=75
result = case score
when 0...50 then "Fail"
when 50...70 then "Pass"
when 70...90 then "Pass with Merit"
when 90..100 then "Pass with Distinction"
else "Invalid Score"
end
puts result #Pass with Merit
case retorna la expresión del primer when que evalúa a
true.
El criterio del when puede ser cualquier instancia, ésta se comparará
con el argumento del case usando el método ===.
------------------------------------------------------------- Object#===
obj === other => true or false
------------------------------------------------------------------------
Case Equality---For class +Object+, effectively the same as calling
+#==+, but typically overridden by descendents to provide
meaningful semantics in +case+ statements.
20. for / while / until
array= ["fresa", "platano", "piña"]
for i in (0...array.length)
puts "En la posicion #{i}, #{array[i]}"
end
i=0
while i < array.legth
puts "En la posicion #{i}, #{array[i]}"
i+=1
end
i=0
until i==array.legth
puts "En la posicion #{i}, #{array[i]}"
i+=1
end
21. Gestión de excepciones
Lanzamiento
Gestión
def invert(x)
raise ArgumentError, "#{x} no es un numero" unless x.is_a? Numeric
1.0 / x
end
*Ejecutar en terminal $ri Kernel#raise
require "open-uri"
def check_connection(max_tries=2, url="http://www.ruby-lang.org")
tries=0
begin
tries+=1
puts "Comprobando conexión"
open(url){puts "Ok!"}
rescue Exception => e
puts "Conexión fallida: #{e.message}"
retry unless tries >= max_tries
end
end
22. Módulos y Mix-ins
• Crean espacios de nombres y previenen colisiones
• Los módulos permiten articular mixins (herencia múltiple de
comportamiento)
Los módulos son una primitiva del lenguaje que permite
agrupar métodos, clases, constantes, etc.
modules.rb
23. Train yourself
http://www.rubyquiz.com/
Crear un programa que dado un número, calcule su
representación en forma de displays de 7 segmentos. El
programa recibirá el número a representar, y el tamaño
del dígito.
> lcd.rb -s 2 012345
-- -- -- --
| | | | | | | |
| | | | | | | |
-- -- -- --
| | | | | | |
| | | | | | |
-- -- -- --
> lcd.rb -s 1 6789
- - - -
| | | | | |
- - -
| | | | | |
- - -