Ruby se diseñó con un criterio poco frecuente y declarado por su autor: la felicidad de quien programa. De esa decisión salieron un lenguaje extraordinariamente expresivo, un marco web que cambió la industria, y buena parte de las prácticas ágiles que hoy se dan por supuestas.
🎯 Por qué está en este programa
Ruby es un primo de la familia de scripting dinámico (Atlas), cuyos representantes en el núcleo son Python y PHP. Es uno de los tres primos que se verifican en CI en cada clase, junto a Perl y Lua.
Aporta al programa el modelo de objetos más puro de todos los lenguajes de uso masivo —todo es un objeto, incluidos los números y
nil, como en Smalltalk (clase 111)— y los bloques, que son la forma más elegante de la clase 121 en un lenguaje mayoritario.
| Año | 1995; 1.9 con la máquina virtual YARV (2007); 3.0 en 2020 |
| Autoría | Yukihiro Matsumoto ("Matz"), Japón |
| Familia | Scripting dinámico; con Smalltalk, Perl, Lisp y Eiffel dentro |
| Paradigma | Orientado a objetos puro, con fuerte componente funcional |
| Tipado | Dinámico y fuerte, con tipos gradual y opcionalmente comprobados (RBS) |
| Memoria | Recolección de basura generacional e incremental |
| Ejecución | Bytecode sobre YARV, con JIT (YJIT) desde 3.1 |
| Estado | 🟢 Muy vivo en web y automatización; Rails sigue siendo referencia |
Yukihiro Matsumoto quería, en 1993, un lenguaje de guion verdaderamente orientado a objetos. Perl era potente y no era OO; Python era OO y —en su opinión— no lo bastante. Su frase resume el criterio de diseño:
"Ruby está diseñado para hacer felices a los programadores."
Eso no es marketing: es una decisión de ingeniería con consecuencias. Cuando hay varias formas de escribir algo, Ruby suele permitir todas, y elige como idiomática la que se lee mejor en voz alta. Es lo contrario del "solo una forma obvia" de Python, y la comparación entre los dos es uno de los contrastes más instructivos de este Atlas.
Ruby fue popular en Japón durante años y desconocido fuera. En 2004, David Heinemeier Hansson publicó Ruby on Rails, y eso lo cambió todo: Rails llevó al mundo entero la convención sobre la configuración, los generadores de código, las migraciones de base de datos y una forma de trabajar que hoy está en Django, Laravel, Phoenix y media docena más.
Y con Rails llegó también una cultura de pruebas —RSpec, Cucumber, el desarrollo dirigido por pruebas como norma— que salió del ecosistema Ruby hacia todos los demás (clase 139).
Después vino la corrección del talón de Aquiles: YARV (1.9) sustituyó al intérprete de árbol, Ruby 3.0 (2020) cumplió el objetivo "Ruby 3x3" —tres veces más rápido que 2.0— y YJIT, escrito en Rust por Shopify, ha dado saltos grandes de rendimiento en producción real.
Uno, la pureza del modelo de objetos (clase 111):
5.class # Integer
5.times { |i| puts i }
nil.to_a # [] ← hasta nil es un objeto con métodos
Integer.ancestors # [Integer, Numeric, Comparable, Object, Kernel, BasicObject]
No hay tipos primitivos. En Java int no es un objeto y hay que envolverlo; en Ruby,
como en Smalltalk, no existe esa distinción — y eso hace el lenguaje uniforme a
costa de rendimiento, que es lo que YJIT recupera con las cachés de envío de la clase 152.
Dos, los bloques, que son la aportación más reconocible:
[1, 2, 3].map { |x| x * 2 }
File.open("datos.txt") do |f| # ← el fichero se cierra SOLO al salir del bloque
f.each_line { |l| puts l }
end
Un bloque es un trozo de código que se pasa a un método, y el método decide cuándo y cuántas veces
ejecutarlo. Eso da a la vez iteración (clase 115) y gestión de recursos (clase 132) — el
File.open con bloque es RAII sin destructores, y el with de Python y el try-with-resources de
Java persiguen lo mismo con más ceremonia.
Y tres, las clases abiertas, que son su característica más potente y más peligrosa:
class String
def gritar = upcase + "!"
end
"hola".gritar # "HOLA!"
Se puede añadir un método a cualquier clase, incluidas las del sistema. Es lo que hace posible la
expresividad de Rails —2.days.ago, "texto".pluralize— y también lo que produce el problema que la
comunidad llama monkey patching: dos bibliotecas que parchean lo mismo, y un fallo que nadie sabe
de dónde viene (clase 150).
Ruby lo reconoció y dio una solución (clase 146): los refinamientos (
refine/using) limitan el parche al ámbito donde se activa. Es un buen ejemplo de un lenguaje corrigiendo su propio exceso sin quitar la característica.
case/in, 2.7) con desestructuración de arreglos y hash.Bundler con Gemfile.lock: es de 2010 y fue uno de los primeros ficheros de bloqueo
populares (clase 143), un modelo que copiaron después npm, Cargo y Composer.ruby main.rb < entrada.txt # el comando de la clase 041
bundle install # dependencias, con Gemfile.lock (clase 143)
rubocop && rspec # estilo y pruebas (clases 139 y 146)
ruby --yjit main.rb # con el JIT activado
Esta versión se ejecuta y se verifica en CI contra el mismo casos.json que el núcleo.
precio, cantidad, descuento = STDIN.gets.split.map(&:to_f)
total = precio * cantidad * (1 - descuento)
puts format("Total: %.2f", total)
Lo que hay que ver.
&:to_f es un símbolo convertido en bloque: el idioma más característico de Ruby. Equivale a
{ |x| x.to_f }, y aprovecha que to_f es un método del objeto — otra vez la pureza del modelo.split sin argumentos parte por espacios en blanco, como strings.Fields en Go y
split ' ' en Perl.format con %.2f viene de C, vía Perl: la herencia se ve.⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Python · Perl · Smalltalk · Elixir · Lua