Crystal: Lenguaje de programación inspirado en Ruby

Publicado el Miércoles, 13 de marzo de 2019

Lenguaje de programación Crystal

Crystal es un lenguaje de programación de propósito general orientado a objetos. Su sintaxis está inspirada en Ruby pero no busca ser compatible. Surgió del amor a la eficiencia para escribir código de Ruby, y el amor a la eficiencia para ejecutar código C. Busca ser lo mejor de ambos mundos.

Entre las diferencias fundamentales con Ruby se encuentran:

  • Es un lenguaje compilado, el código es convertido a código de máquina nativo a través de LLVM. Ruby, por otro lado, es un lenguaje interpretado.
  • Tiene un sistema de tipado estático, por lo que la comprobación de tipos se realiza durante la compilación. Esto agrega una capa más de seguridad al código, evitando errors de tipos. Ruby es dinámicamente tipado, por lo que los tipos se revisan en ejecución. Sin embargo, el compilador de Crystal cuenta con un sistema de inferencia de tipos, por lo que no es necesario declarar los tipos de todos los valores y ejecuciones ya que el compilador los puede detectar. De esta manera, el código se mantiene limpio, y esto es parte de la filosofía del lenguaje.

El siguiente código nos muestra la inferencia de tipos en acción:

puts typeof("Fernando") #=> String
puts typeof(12) #=> Int32
puts typeof(42.0) #=> Float64

También podemos definir el tipo con anotaciones:

@nombre : String
@edad : Int32

Todo es un objeto: Al igual que en Ruby, en Crystal todo es un objeto (tiene un tipo, responde a algunos métodos).

Recién va por la versión 0.27.2, así que está creciendo y cambiando rápidamente todavía. De todas formas hay algunos valientes que se han animado a usarlo en producción. El proyecto cuenta con un Roadmap que define las cosas que quieren tener en el lenguaje, así como preguntas frecuentes y una excelente documentación.

Otras cosas interesantes de Crystal sobre las que me gustaría escribir más adelante: union types (tipos de datos especiales que pueden poseer varias representaciones), Macros (sistema para meta programación), Modelo de concurrencia e integración con librerías C (tiene una sintaxis dedicada para llamar a bibliotecas nativas de forma sencilla).

Instalar Crystal

Crystal puede ser instalado en Debian, Ubuntu, RedHat, CentOS, Arch Linux, Gentoo, Alpine, FreeBSD, y demás sistemas, desde un tar.gz o compilado desde el código fuente. Si usan el gestor de versiones asdf, hay un plugin para eso. Podemos ver las distintas instrucciones de instalación en la documentación.

El comando crystal

Una vez instalado, deberíamos tener el comando crystal disponible en nuestra terminal. Los archivos de código fuente Crystal tienen la extensión .cr. Para ejecutar un archivo de código fuente Crystal, escribimos:

$ crystal run archivo.cr

El comando `run` compila el código a un binario ejecutable en una ubicación temporal y lo ejecuta. Con el comando crystal build, podemos crear un binario ejecutable:

Crystal build

También existe crystal eval para pasarle código Crystal a crystal run desde la línea de comando o a través de un pipe por la entrada estándar. La lista completa de opciones está en la documentación usando el compilador.

Creando proyectos Crystal

El comando crystal también incluye el parámetro init, que inicializa un directorio con un proyecto. El primer parámetro de init es el tipo de proyecto. Las dos opciones son lib, una biblioteca reutilizable y app, una aplicación sin el objetivo de ser usada como dependencia:


$ crystal init app prueba
create prueba/.gitignore
create prueba/.editorconfig
create prueba/LICENSE
create prueba/README.md
create prueba/.travis.yml
create prueba/shard.yml
create prueba/src/prueba.cr
create prueba/spec/spec_helper.cr
create prueba/spec/prueba_spec.cr
Initialised empty Git repository in /home/fernando/workspace/crystal/prueba/.git/

Shards: Manejo de dependencias

Shards es a Crystal lo que las gemas son a Ruby. Las aplicaciones y bibliotecas Crystal cuentan con un archivo shard.yml que declara las dependencias del proyecto. Shards se distribuye con Crystal, así que lo tenemos disponible en nuestra terminal. Con shard init, creamos un archivo shard.yml de ejemplo, seguido de shard install para instalar las dependencias y especificarlas en un archivo shard.lock.

Por ejemplo en el proyecto recién creado, agrego las siguientes líneas al archivo shard.yml:

dependencies:
  cossack:
    github: crystal-community/cossack
    version: ~> 0.1
  

Cossack es un cliente HTTP bastante simple para Crystal. Se instala al ejecutar shards install y ya lo puedo usar en el código fuente. Dentro del archivo src/prueba.cr del mismo proyecto escribo:

require "cossack"
 
module Prueba
  VERSION = "0.1.0"
 
  def self.hola
    response = Cossack.get("https://picandocodigo.net/api")
    puts response.body
  end
end
 
Prueba.hola

Y podemos ejecutarlo con crystal run para ver los resultados:
crystal run src/prueba.cr

Testeando Código Crystal

Crystal viene equipado con una biblioteca de testing en el módulo Spec. Incluye un DSL (lenguaje de dominio específico) inspirado en RSpec, por lo que resulta súper familiar para programadores Ruby. Cuando inicié mi proyecto más arriba,ya se creó un directorio /spec con un archivo de ejemplo. Modificando un poco el archivo prueba.cr para que retorne el valor de lo que obtiene Cossack en vez de imprimirlo en pantalla con puts, podemos escribir un test bastante sencillo:

describe Prueba do
  it "calls Picando Código's API" do
    Prueba.hola.should eq "¡Chau!"
  end
end

Y si corremos los tests, tenemos una falla! (TDDeando, por supuesto):

$ crystal spec
F

Failures:

1) Prueba calls Picando Código's API
Failure/Error: Prueba.hola.should eq "¡Chau!"

Expected: "¡Chau!"
got: "¡Hola!"

# spec/prueba_spec.cr:5

Finished in 744.67 milliseconds
1 examples, 1 failures, 0 errors, 0 pending

Failed examples:

crystal spec spec/prueba_spec.cr:4 # Prueba calls Picando Código's API

Cambiando la expectativa del test a "¡Hola!" hacemos que pase:

describe Prueba do
  it "calls Picando Código's API" do
    Prueba.hola.should eq "¡Hola!"
  end
end
$ crystal spec
.

Finished in 861.99 milliseconds
1 examples, 0 failures, 0 errors, 0 pending

Como ven, es bastante sencillo empezar a usar Crystal. Espero con este post lograr despertar el interés por el lenguaje, y con suerte tener algún intercambio al respecto. Los comentarios están abiertos si quieren dejar su opinión, ¿conocían Crystal? ¿Le ven futuro?

Por mi parte voy a seguir investigando el lenguaje e intentar escribir algunos proyectitos, así como analizar las herramientas ya disponibles, e iré compartiéndolo por acá.

Más información sobre Crystal:

No hay comentarios en este post

Feed de comentarios

Dejar un comentario

Toasty!