Translate
viernes, 23 de agosto de 2024
jueves, 11 de julio de 2024
Como podemos manejar las referencias nulas?
El error más frecuente en Java es NullPointerException y me imagino que en otros lenguajes alguno similar... Para abordar esto, se han introducido estructuras y operadores que ayudan a manejar la ausencia de valores de manera más segura y explícita.
Por ejemplo en Java se introdujo la clase `Optional` en la versión 8 para manejar valores potencialmente nulos de una manera más segura. `Optional` es un contenedor que puede o no contener un valor no nulo.
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> optional = Optional.of("Hello, World!");
// Verificar si hay un valor presente
if (optional.isPresent()) {
System.out.println(optional.get());
}
// Uso del método ifPresent
optional.ifPresent(System.out::println);
// Proveer un valor predeterminado
String value = optional.orElse("Default Value");
System.out.println(value);
// Proveer un valor predeterminado usando un Supplier
value = optional.orElseGet(() -> "Default Value from Supplier");
System.out.println(value);
}
}
Scala utiliza la clase `Option` para representar un valor opcional. `Option` tiene dos subclases: `Some` y `None`, lo que proporciona una forma elegante y funcional de manejar valores que pueden estar ausentes. Esta idea es similar a la monada `Maybe` en Haskell.
object OptionExample extends App {
val someValue: Option[String] = Some("Hello, World!")
val noneValue: Option[String] = None
// Uso de getOrElse
println(someValue.getOrElse("Default Value"))
println(noneValue.getOrElse("Default Value"))
// Uso del patrón de coincidencia (Pattern Matching)
someValue match {
case Some(value) => println(value)
case None => println("No value")
}
noneValue match {
case Some(value) => println(value)
case None => println("No value")
}
}
Scala "copio" esta forma de Haskell. Haskell utiliza el tipo de datos `Maybe` para manejar valores opcionales `Maybe` puede ser `Just` un valor o `Nothing`.
main :: IO ()
main = do
let someValue = Just "Hello, World!"
let noneValue = Nothing
-- Uso de fromMaybe
putStrLn (fromMaybe "Default Value" someValue)
putStrLn (fromMaybe "Default Value" noneValue)
-- Uso del patrón de coincidencia (Pattern Matching)
case someValue of
Just value -> putStrLn value
Nothing -> putStrLn "No value"
case noneValue of
Just value -> putStrLn value
Nothing -> putStrLn "No value"
Kotlin es similar a Scala en muchos aspectos pero no en este. Kotlin introduce el operador `?` para facilitar la gestión de valores nulos. Este operador se utiliza para declarar tipos de datos que pueden ser nulos y para realizar operaciones seguras contra nulos.
fun main() {
var nullableString: String? = "Hello, World!"
// Uso del operador ?. para llamadas seguras
println(nullableString?.length)
// Uso del operador ?: para proporcionar un valor predeterminado
val length = nullableString?.length ?: 0
println(length)
nullableString = null
// Uso de let para ejecutar código solo si el valor no es nulo
nullableString?.let {
println(it)
}
}
C# ha incluido varias características para manejar valores nulos, como el operador `?`, que facilita el manejo seguro de tipos que pueden ser nulos.
using System;
class Program
{
static void Main()
{
string? nullableString = "Hello, World!";
// Uso del operador ?. para llamadas seguras
Console.WriteLine(nullableString?.Length);
// Uso del operador ?? para proporcionar un valor predeterminado
int length = nullableString?.Length ?? 0;
Console.WriteLine(length);
nullableString = null;
// Uso de pattern matching para verificar nulos
if (nullableString is string nonNullString)
{
Console.WriteLine(nonNullString);
}
}
}
Rust maneja la ausencia de valores y los errores de una manera robusta utilizando los tipos `Option` y `Result`. `Option` puede ser `Some` o `None`, mientras que `Result` puede ser `Ok` o `Err`.
fn main() {
let some_value: Option<String> = Some("Hello, World!".to_string());
let none_value: Option<String> = None;
// Uso de unwrap_or
println!("{}", some_value.unwrap_or("Default Value".to_string()));
println!("{}", none_value.unwrap_or("Default Value".to_string()));
// Uso del patrón de coincidencia (Pattern Matching)
match some_value {
Some(value) => println!("{}", value),
None => println!("No value"),
}
match none_value {
Some(value) => println!("{}", value),
None => println!("No value"),
}
}
Go no tiene un tipo de datos específico para manejar valores opcionales, pero utiliza la convención de retornar múltiples valores, incluyendo un valor y un `error`. Que la verdad no me gusta, te pasas preguntando todo el tiempo si hay error o si los valores son nulos.
package main
import (
"errors"
"fmt"
)
func getValue() (string, error) {
return "Hello, World!", nil
}
func getNullableValue() (string, error) {
return "", errors.New("no value")
}
func main() {
value, err := getValue()
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Value:", value)
}
nullableValue, err := getNullableValue()
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Value:", nullableValue)
}
}
Python utiliza la palabra clave `None` para representar la ausencia de valor. Aunque no tiene una estructura específica como `Optional`, los desarrolladores pueden utilizar condicionales y manejo de excepciones.
def get_value():
return "Hello, World!"
def get_nullable_value():
return None
value = get_value()
nullable_value = get_nullable_value()
if value is not None:
print(value)
else:
print("Default Value")
if nullable_value is not None:
print(nullable_value)
else:
print("Default Value")
Ruby utiliza `nil` para representar la ausencia de valor. Al igual que en Python, no tiene una estructura específica para valores opcionales, pero proporciona métodos para manejar `nil`.
value = "Hello, World!"
nullable_value = nil
# Uso del operador ||
puts value || "Default Value"
puts nullable_value || "Default Value"
# Uso de condicionales
puts value.nil? ? "Default Value" : value
puts nullable_value.nil? ? "Default Value" : nullable_value
C++ utiliza punteros inteligentes (`smart pointers`) para gestionar la memoria y prevenir errores relacionados con punteros nulos. Los punteros inteligentes, como `std::unique_ptr` y `std::shared_ptr`, se encargan de la gestión automática de la memoria.
#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> uniquePtr(new int(42));
if (uniquePtr) {
std::cout << *uniquePtr << std::endl;
}
std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);
if (sharedPtr) {
std::cout << *sharedPtr << std::endl;
}
// Uso de weak_ptr para evitar ciclos de referencia
std::weak_ptr<int> weakPtr = sharedPtr;
if (auto lockedPtr = weakPtr.lock()) {
std::cout << *lockedPtr << std::endl;
}
return 0;
}
TypeScript, un superconjunto de JavaScript, permite tipos opcionales y tiene un soporte robusto para manejar valores `null` y `undefined`.
let nullableString: string | null = "Hello, World!";
// Uso del operador ? para llamadas seguras
console.log(nullableString?.length ?? 0);
// Uso de if para asegurar valores no nulos
if (nullableString !== null) {
console.log(nullableString);
}
TypeScript utiliza tipos opcionales para manejar valores que pueden ser `null` o `undefined`, proporcionando un enfoque seguro para evitar errores comunes relacionados con valores nulos. El operador `?.` permite realizar llamadas seguras, y el operador `??` proporciona valores predeterminados en caso de valores `null` o `undefined`.
En fin, aunque la gestión de valores nulos varía entre lenguajes, la idea subyacente es la misma: proporcionar mecanismos más seguros y expresivos para manejar la ausencia de valores. Ya sea mediante clases contenedoras como `Optional` en Java y `Option` en Scala, tipos de datos como `Maybe` en Haskell, operadores específicos como `?` en Kotlin y C#, punteros inteligentes en C++, o enfoques específicos en Rust, Go, Python y Ruby, estos enfoques ayudan a reducir los errores y a escribir un código más robusto y mantenible.
viernes, 24 de febrero de 2023
Programación poliglota con GraalVM parte 2
Seguimos con GraalVM
Veamos un ejemplo queremos ejecutar una aplicación javascript o node que dentro llama a codigo ruby, por ejemplo.
Vamos a tener que crear un archivo .js que lo llamaré ejemplo.js que contenga lo siguiente:
var array = Polyglot.eval("ruby", "[1,2,42,4]")
console.log(array[2]);
Y lo ejecutamos con :
js --polyglot --jvm ejemplo.js
42
node --polyglot --jvm ejemplo.js
42
Y puedo seguir con ejemplos pero creo que se entiende :D
Dejo link : https://www.graalvm.org/reference-manual/polyglot-programming/#running-polyglot-applications
jueves, 2 de junio de 2022
Why Ruby?
¿Quieres trabajar con Ruby pero no conoces el lenguaje? Nos hemos encontrado múltiples compañías que buscan profesionales que quieran cambiar su stack y aprender Ruby. ¿Te interesa?
Así comienza esta pagina que tiene como objetivo ampliar el mercado laboral de ruby. Si ya te intereso dejo el link :
sábado, 5 de diciembre de 2020
Top 10 de los lenguajes de programación más populares en GitHub
Github liberó el resultado de una métrica que indica cual es el lenguaje más utilizado en su repositorio. Y el ganador por tercer año consecutivo es Javascript.
El que sorprendió fue typescript, recuperándose de un 2019 no tan bondadoso.
Y listo, no hay otras novedades...
miércoles, 23 de septiembre de 2020
Por qué GraalVM?
Lo único malo que veo en GraslVM es el marketing que están llevando. Dado que GraalVM es un proyecto paraguas donde hay varios proyectos. Entre los que tenemos una maquina virtual más rápida, la capacidad de compilar nuestras aplicaciones de forma nativa o diferentes plataformas o ejecutar varios lenguajes.
viernes, 28 de agosto de 2020
Que lenguaje de programación debo aprender?
Este es un post de opinión no me apoyo en ninguna encuesta o nada, es opinión de lo que voy leyendo. A la vez ya hice post similares pero lo actualice a 2020.
Dicho esto, me pongo a opinar. Si queres aprender un lenguaje de programación, lo que primero que debes hacer es pensar a que te queres dedicar. Dado que la programación tiene varios objetivos y si bien hay lenguajes que son buenos para todo pero no son populares en todo, por lo tanto, dependiendo a que te queres dedicar es el lenguaje que debes aprender.
Voy a listar temas y poniendo los lenguajes.
Backend : Java, C#, Kotlin, Scala, Groovy, PHP, Python, Haskell, Go, SQL, Ruby
Frontend : Javascript, Typescript, Elm
Mobile : Java, Kotlin, C#, Dart
Data science : SQL, Python, Julia, R
Sistemas (bajo nivel) : Rust, Go, C
Sistemas concurrentes : Rust, Go, Scala, Haskell, Erlang, Elixir
Juegos : C, C++, Rust, Go, Lua, Elm, C#
lunes, 1 de junio de 2020
repl.it, Una super IDE online
Dejo link: https://repl.it/
miércoles, 6 de mayo de 2020
El estado del ecosistema del desarrollador 2019
martes, 27 de agosto de 2019
Indice TIOBE de agosto
Como se puede ver Python va subiendo tranquilo, a mi entender esto viene de la mano de las tecnologías de machine learnig que cada vez están más presentes y todas las librerías están en Python.
Otro lenguaje que viene creciendo es Groovy, a mi entender gracias a Spring y pivotal
Dejo link:
https://www.tiobe.com/tiobe-index/
lunes, 12 de agosto de 2019
Haciendo aplicaciones políglotas con GraalVM
GraalVM permite compartir el mismo runtime, eliminando la aislamiento y permitiendo la interoperabilidad entre programas que estén escritos en diferente lenguajes. Puede correr como “standalone” o por medio de la Open-Jdk o Node.js o por la base de datos oracle.
GraalVM permite escribir poliglotas programas con cero overhead y con alta interoperabilidad. De esta manera que se pueden escribir diferentes partes del código en diferentes lenguajes.
const express = require('express');
const app = express();
app.listen(3000);
app.get('/', function(req, res) {
var text = 'Hello World!';
const BigInteger = Java.type(
'java.math.BigInteger');
text += BigInteger.valueOf(2)
.pow(100).toString(16);
text += Polyglot.eval(
'R', 'runif(100)')[0];
res.send(text);
})
También podemos crear imágenes de nuestras aplicaciones Java, lo que permite que corran mucho más rápido, en una plataforma determinada.
$ javac HelloWorld.java
$ time java HelloWorld
user 0.070s
$ native-image HelloWorld
$ time ./helloworld
user 0.005s
GraalVm puede ser embebido en aplicaciones Java que utilicen el openjdk o node.js o base de datos oracle. De esta manera podemos ejecutar código de otro lenguaje :
import org.graalvm.polyglot.*;
public class HelloPolyglot {
public static void main(String[] args) {
System.out.println("Hello Java!");
Context context = Context.create();
context.eval("js",
"print('Hello JavaScript!');");
}
}
Es muy bueno, dejo el link:
https://www.graalvm.org/
domingo, 31 de marzo de 2019
Por qué Cristal es un lenguaje de programación importante?
Parece una tontería pero permite obtener código de tipado estático, lo cual nos trae con sigo una herramienta fundamental para la búsqueda de errores que es el chequeo por tipo. Sin tener que sacrificar casi nada de nuestro lenguaje de tipado dinámico.
Digo casi nada porque por ejemplo no podemos cambiar el tipo de una variable, por ejemplo :
var a = 2
a = "hola"
no compilaría, pero la pregunta del millón es ¿ eso es útil ?
Es decir a alguien realmente le interesa cambiar de tipo una variable, yo creo que no. No escribo código de tipado dinámico pero imagino, que no existe un interés de reutilizar las variables. Por lo tanto festejo que no se pueda hacer esto en Cristal.
Por ultimo, ¿que piensan, otros lenguajes le seguirán los pasos a Cristal?
Dejo link: https://crystal-lang.org/
jueves, 25 de octubre de 2018
The State of the Octoverse
Github publico el informe anual Octoverse, en el cual se pueden ver datos interesantes de los proyecto. El informe es grande y tiene muchos detalles.
En especial me intereso los lenguajes más utilizados:
No tengo mucho análisis para hacer javascript viene primero y es indiscutido. Y como lenguajes con mayor crecimiento podemos ver como impacto la decisión de Android de dar soporte a Kotlin :
Me llamo la atención no ver a Scala, pero bueno... dejen su opinión.
Dejo link: https://octoverse.github.com/
viernes, 7 de septiembre de 2018
Los mejores lenguajes de programación para Blockchain
Quiero compartir un post sobre lenguajes para programar en Blockchain, por que lo comparto? Porque es uno de los poco top que trae con sigo lenguajes originales hasta hay algunos que no conozco y ya voy a estudiar!
Claramente tienen que aparecer los lenguajes de moda y como están de moda existe una librería para casi todo: Java, C++, Python, javascript, Ruby.
Pero entre las novedades tenemos a : Solidity, Simplicity, Rholang.
Solidity es un lenguaje de alto nivel orientado a contratos. Fue influenciado por C ++, Python y JavaScript y está diseñado para la Máquina Virtual Ethereum (EVM).
Simplicity : un nuevo lenguaje para Blockchains. Y ya lo voy a estudiar.
Rholang es un lenguaje de programación concurrente, con un enfoque en el envío de mensajes y formalmente modelado por el cálculo ρ, una extensión reflexiva de orden superior del cálculo π. Está diseñado para ser utilizado para implementar protocolos y "contratos inteligentes" en una cadena de bloques de propósito general, pero también podría usarse en otros entornos.
Sin más dejo el post: https://www.geekboots.com/story/top-languages-that-are-best-for-blockchain-programming
miércoles, 10 de enero de 2018
Lenguajes de programación para aprender en 2018
Si bien el articulo no presenta mayor sorpresa, lista los lenguajes más populares de 2017 y que seguirán fuerte en 2018. Ojo aparece Scala (esto me llamo mucho la atención)
Yo empece el año con Crystal y se lo recomiendo porque esta muy bueno el lenguaje.
Dejo link: https://platzi.com/blog/lenguajes-de-programacion-2018/?utm_source=facebook&utm_medium=paidsocial&utm_campaign=pubetapa0
sábado, 6 de enero de 2018
Ruby + C = Crystal
Veamos un ejemplo:
# A very basic HTTP server
require "http/server"
server = HTTP::Server.new(8080) do |context|
context.response.content_type = "text/plain"
context.response.print "Hello world, got #{context.request.path}!"
end
puts "Listening on http://127.0.0.1:8080"
server.listen
Este pequeño ejemplo hemos montado un servidor web con una página de ejemplo.
Crystal tiene chequeo de tipo forma estática, por lo que el compilador detectará cualquier tipo de error antes de que falle en el tiempo de ejecución. Además, y para mantener el lenguaje limpio, Crystal tiene inferencia de tipos, por lo que no es necesario indicar el tipo la mayoría de las veces.
def shout(x)
# Notice that both Int32 and String respond_to `to_s`
x.to_s.upcase
end
foo = ENV["FOO"]? || 10
typeof(foo) # => (Int32 | String)
typeof(shout(foo)) # => String
Los tipos no permiten null y las variables nullable se representan como una unión entre el tipo y null. Como consecuencia, el compilador comprobará automáticamente si hay referencias nulas en tiempo de compilación.
if rand(2) > 0
my_string = "hello world"
end
puts my_string.upcase
Si corremos esto :
$ crystal hello_world.cr
Error in hello_world.cr:5: undefined method 'upcase' for Nil (compile-time type is (String | Nil))
puts my_string.upcase
Crystal posee un potente sistema de macro , que abarca desde la inspección básica de plantillas y AST hasta la inspección de tipos y la ejecución de programas externos arbitrarios.
class Object
def has_instance_var?(name) : Bool
{{ @type.instance_vars.map &.name.stringify }}.includes? name
end
end
person = Person.new "John", 30
person.has_instance_var?("name") #=> true
person.has_instance_var?("birthday") #=> false
Crystal usa hilos verdes, llamados fibras, para lograr concurrencia. Las fibras se comunican entre sí mediante canales, como en Go o Clojure, sin tener que recurrir a la memoria compartida o bloqueos.
channel = Channel(Int32).new
total_lines = 0
files = Dir.glob("*.txt")
files.each do |f|
spawn do
lines = File.read(f).lines.size
channel.send lines
end
end
files.size.times do
total_lines += channel.receive
end
puts total_lines
Crystal tiene una sintaxis dedicada para llamar fácilmente a bibliotecas nativas, eliminando la necesidad de volver a implementar tareas de bajo nivel.
# Fragment of the BigInt implementation that uses GMP
@[Link("gmp")]
lib LibGMP
alias Int = LibC::Int
alias ULong = LibC::ULong
struct MPZ
_mp_alloc : Int32
_mp_size : Int32
_mp_d : ULong*
end
fun init_set_str = __gmpz_init_set_str(rop : MPZ*, str : UInt8*, base : Int) : Int
fun cmp = __gmpz_cmp(op1 : MPZ*, op2 : MPZ*) : Int
end
struct BigInt < Int
def initialize(str : String, base = 10)
err = LibGMP.init_set_str(out @mpz, str, base)
raise ArgumentError.new("invalid BigInt: #{str}") if err == -1
end
def <=>(other : BigInt)
LibGMP.cmp(mpz, other)
end
end
Las bibliotecas de Crystal se empaquetan como fragmentos y se distribuyen a través de Git sin necesidad de un repositorio centralizado. Los comandos incorporados permiten que las dependencias se especifiquen fácilmente a través de un archivo YAML y se obtengan de sus respectivos repositorios.
name: my-project
version: 0.1
license: MIT
crystal: 0.21.0
dependencies:
mysql:
github: crystal-lang/crystal-mysql
version: ~> 0.3.1
Esto es solo un post de muestra. Para empezar de lleno vamos a tener que instalar el lenguaje y luego a estudiar, pero esos serán otros post.
Dejo link: https://crystal-lang.org/
https://github.com/crystal-lang/crystal/
lunes, 16 de octubre de 2017
Los 15 lenguajes más utilizados en github
Veamos todos:
Rank | Language | Pull Requests |
1 | JavaScript | 2.3M |
2 | Python | 1M |
3 | Java | 986K |
4 | Ruby | 870K |
5 | PHP | 559K |
6 | C++ | 413K |
7 | CSS | 335K |
8 | C# | 326K |
9 | Go | 285K |
10 | C | 239K |
11 | TypeScript | 207K |
12 | Shell | 206K |
13 | Swift | 107K |
14 | Scala | 99K |
15 | Objective C | 66K |
GitHub también ha compartido algunos puntos de vista sobre la mayoría de las organizaciones y proyectos activos por la cantidad de colaboradores únicos, forks y comentarios. Y aquí están los datos sobre ellos.
Un vistazo a los datos anuales de GitHub:
- 24 millones de usuarios totales
- 1,5 millones de organizaciones
- 67 millones de depósitos totales
- 1 mil millones de compromisos públicos desde septiembre de 2016
- 25,3 millones de depósitos activos desde septiembre de 2016
- 1,3 millones de nuevas solicitudes desde septiembre de 2016
Dejo el articulo: https://curiouspost.com/list-15-popular-programming-languages-used-coders-github/
sábado, 1 de julio de 2017
Que cursos de codeschool puedo hacer de forma gratuita?
Try C#
viernes, 9 de junio de 2017
Cristal, rápido como C, amigable como Ruby
Cristal es un lenguaje similar a ruby que viene creciendo bastante, entre sus características podemos nombrar:
Sintaxis: La sintaxis de cristal es muy similar a la de ruby, lo que lo hace fácil de leer y de escribir.
Veamos un ejemplo:
# A very basic HTTP server
require "http/server"
server = HTTP::Server.new(8080) do |context|
context.response.content_type = "text/plain"
context.response.print "Hello world, got #{context.request.path}!"
end
puts "Listening on http://127.0.0.1:8080"
server.listen
Es un lenguaje compilado, lo que lo hace más rápido y con menos uso de memoria.
Chequeo de tipos, cristal es de tipado estático y hace chequeos de tipo en tiempo de compilación.
Chequeo de posibles errores por valores nulos.
if rand(2) > 0
my_string = "hello world"
end
puts my_string.upcase
y si compilamos:
$ crystal hello_world.cr
Error in hello_world.cr:5: undefined method 'upcase' for Nil (compile-time type is (String | Nil))
puts my_string.upcase
^~~~~~
Macros, que permiten extender el lenguaje:
class Object
def has_instance_var?(name) : Bool
{{ @type.instance_vars.map &.name.stringify }}.includes? name
end
end
person = Person.new "John", 30
person.has_instance_var?("name") #=> true
person.has_instance_var?("birthday") #=> false
y mucho más!!
Dejo link:
https://crystal-lang.org/
miércoles, 10 de mayo de 2017
Primeros pasos en Sinatra
Donde nos lleva la vida, no? Nunca pensé que tenia que retomar mis estudios en ruby y mucho menos con Sinatra. Pero esta bueno, volver a leer un lenguaje que me gusta mucho.
Si quieren saber que es Sinatra, acá tenemos un post:
http://emanuelpeg.blogspot.com.ar/2012/11/sinatra-rapida-creacion-de-aplicaciones.html
Empecemos por el principio, instalar Ruby. Eso es muy fácil y si usan linux :
sudo apt-get install ruby-full
En distros Debian, Ubuntu, Mint o cualquier derivado de debian que use apt.
$ sudo yum install ruby
En distros rhel y para otras distros: https://www.ruby-lang.org/es/documentation/installation/
También tenemos que instalar el software de instalación de paquetes RubyGem.
$ sudo apt-get install rubygems
En distros Debian, Ubuntu, Mint o cualquier derivado de debian que use apt.
$ sudo yum install rubygems
En distros rhel.
Vamos a ver la versión que instalamos con el comando:
ruby -v
Si dice algo así hemos tenido éxito:
ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]
$ gem install sinatra
Esto hará que nuestro sistema descargue todas las dependencias como Rack y otras utilidades, aparte de la documentación oficial para varios de estos componentes, de forma que tengamos ayuda cuando queramos ejecutar algún comando en particular.
Ya una vez que tenemos instalado Sinatra y sus dependencias, empezar a utilizarlo , simplemente debemos crear un nuevo proyecto, es decir, una carpeta donde almacenar nuestros archivos y crear un archivo que llamaremos ejemplo.rb (muy original)
~ $ mkdir ejemplo
~ $ cd ejemplo
~/ejemplo $ nano ejemplo.rb
Y ahora escribimos el siguiente código:
require 'sinatra'
get '/' do
"Hola, mundo!"
end
Y ya estamos, ahora a ejecutarlo:
$ ruby ejemplo.rb
Si todo salio bien tenemos la siguiente salida o parecida :
/var/lib/gems/2.3.0/gems/rack-2.0.2/lib/rack/show_exceptions.rb:16: warning: already initialized constant Rack::ShowExceptions::CONTEXT
/usr/lib/ruby/vendor_ruby/rack/showexceptions.rb:16: warning: previous definition of CONTEXT was here
/var/lib/gems/2.3.0/gems/rack-2.0.2/lib/rack/show_exceptions.rb:114: warning: already initialized constant Rack::ShowExceptions::TEMPLATE
/usr/lib/ruby/vendor_ruby/rack/showexceptions.rb:115: warning: previous definition of TEMPLATE was here
[2017-05-10 22:44:39] INFO WEBrick 1.3.1
[2017-05-10 22:44:39] INFO ruby 2.3.1 (2016-04-26) [x86_64-linux-gnu]
== Sinatra (v1.4.7) has taken the stage on 4567 for development with backup from WEBrick
[2017-05-10 22:44:39] INFO WEBrick::HTTPServer#start: pid=26437 port=4567