style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Explorando el mundo Groovy

Groovy

Últimamente me ha dado la locura de programar en cuanto lenguaje se me ponga en frente, es por ello que hoy toca el turno a Groovy, en este video tutorial aprenderemos a instalarlo configurarlo y hacer el clásico “Hola Mundo Groovy”.

Descargando Groovy
Como casi siempre lo primero que tenemos que hacer para empezar a programar en un lenguaje nuevo, es descargar su SDK o los archivos necesarios que nos permitan programar en él, en este caso vamos a la pagina oficial de Groovy en la sección descargas http://groovy.codehaus.org/Download y descargamos la versión mas reciente (la 1.7.8 al momento de hacer este tutorial, aunque ya está la 1.8 beta 4) déjenme decirles que Groovy es el lenguaje más sencillo de instalar pues aunque ofrece una versión para instalar en Windows lo mejor es descargar los archivos binarios.

Instalando Groovy
Una vez que tenemos el archivo zip con los binarios, descomprimimos la carpeta por ejemplo en c:/Archivos de programa/ o en el lugar que mas les guste.
Ahora vamos a configurar una variable de entorno, GROOVY_HOME en Windows 7 vamos a equipo / propiedades / configuración avanzada del sistema / variables de entorno y agregamos la variable GROOVY_HOME como nombre y en el valor la ruta donde descomprimimos la carpeta (ojo debe ser la carpeta padre de la carpeta bin /como en java) nos debe quedar como se muestra en la imagen:

Groovy

Con esto basta para que podamos trabajar con Groovy pero adicionalemte si gustan pueden agregar la variable GROOVY_HOME\bin al path pero sino no importa.

Hola Mundo en Groovy
Este sencillo paquete de tan solo 14MB apx. ya trae un IDE para que podamos programar en Groovy en la carpeta bin de Groovy esta un archivo .bat llamado groovyConsole.bat lo ejecutamos y podremos ver algo como esto:

groovyConsole

Si ya sé que es un poco sencillo, pero muy funcional aunque los próximos tutoriales los haremos con Idea (si también otra vez IntelliJ Idea pronto se darán cuenta que este editor nos sirve para programar con muchos lenguajes y además ya trae integración con sus principales framewokrs, después de este comercial seguimos.)

Ahora el hola mundo en Groovy es tan sencillo como poner una sola línea:

         print ("hello world");

Ejecutamos con la hojita y una flechita verde y listo debajo vemos la salida.

cortesia de http://robertoleon.com.mx
@FlexJRL

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

version 2

una version mas sencilla del programa: los parentesis son opcionales, y el punto y coma tambien:

println "hola"
Imagen de ezamudio

explorar

Y por cierto, que chido que haya mas gente de esta comunidad explorando Groovy, ya tendre con quien discutir de este tema.

¿Cuales son las reglas para

¿Cuales son las reglas para la "opcionalidad" de los paréntesis? nunca lo he tenido muy claro ( tampoco he querido investigar mucho, la verdad )

No usar paréntesis parece funcionar muy bien cuando el resultado no se asigna a una variable, pero cuando se intenta, hacerlo, surge una ambigüedad y se hacen necesarios:

Ejemplo:

groovy:000> def dime( ... algo ) {
groovy:001>   algo.toString()
groovy:002> }
===> true
groovy:000> dime "Una ", "frase"
===> [Una , frase]

Como se espera. Pero si este resultado se quiere asignar una variable:

groovy:000> loqueQuieroOir = dime "Una", "cancion"
ERROR org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, groovysh_parse: 1: unexpected token: Una @ line 1, column 23.
   loqueQuieroOir = dime "Una", "cancion"
                         ^

1 error

        at java_lang_Runnable$run.call (Unknown Source)

Fayeition, se necesitan los paréntesis.

groovy:000> loqueQuieroOir = dime( "Una", "cancion" )
===> [Una, cancion]

Ahora si.

El problema, mayor viene cuando se quiere usar esta opcionalidad encadenando llamadas

groovy:000> def preguuuntame ( ... algo ) {        
groovy:001> "nooo pos esa si, no te la manejoooOOoo"
groovy:002> }                                      
===> true
groovy:000> preguuuntame "Hay vida despues " , "de la muerte"
===> nooo pos esa si, no te la manejoooOOoo

Funciona, como se espera.

Pero lo siguiente falla ( seguramente por la misma razón que falla asignar el valor de retorno a una variable )

groovy:000> dime "Lo siguiente: ", preguuuntame "funcionas sin paréntesis?"
ERROR org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, groovysh_parse: 1: expecting EOF, found 'funcionas sin paréntesis?' @ line 1, column 37.
   dime "Lo siguiente: ", preguuuntame "funcionas sin paréntesis?"
                                       ^

1 error

        at java_lang_Runnable$run.call (Unknown Source)

Ouch!.

Entonces se tienen que ir regresando los paréntesis:

groovy:000> salud = dime "Lo siguiente: ", preguuuntame("Cuales son las reglas?")
ERROR org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, groovysh_parse: 1: unexpected token: Lo siguiente:  @ line 1, column 14.
   salud = dime "Lo siguiente: ", preguuuntame("Cuales son las reglas?")
                ^

1 error

        at java_lang_Runnable$run.call (Unknown Source)

Nap!

Hasta quedar como antes :-/, con paréntesis forzosos.

groovy:000> salud = dime( "Lo siguiente: ", preguuuntame("Cuales son las reglas?"))
===> [Lo siguiente: , nooo pos esa si, no te la manejoooOOoo]
groovy:000>

Otra cosa que no entiendo bien, es por que no funciona esta opcionalidad cuando no se reciben argumentos:

"Hola".toString()
===>Hola
 "Hola".toString  
ERROR groovy.lang.MissingPropertyException: No such property: toString for class: java.lang.String
        at groovysh_evaluate.run (groovysh_evaluate:2)
groovy:000> def unaFuncion() {
groovy:001>    "soy una funcion"
groovy:002> }
===> true
groovy:000> s = unaFuncion()
groovy:000> s
===> soy una funcion
groovy:000> p = unaFuncion
===> org.codehaus.groovy.runtime.MethodClosure@ecd92c

En el primer caso, dice que el objeto no tiene tal propiedad, y en el segundo devuelve la referencia.

En mi opinión ( quizá derivada de la ignorancia como ha pasado ) los parentesis debería de ser opcionales, solamente en las llamadas a métodos con un solo argumento.

Por lo que:

dime "Algo"

No necesitaría

Pero

dime "Algo", "diferente"

Si necesitaría por tener más de un argumento.

En fin.

Menos mal que la llamada a métodos usando la notación punto "." no es opcional en Groovy, como lo es en Scala. O si?

Imagen de ezamudio

parentesis

cuando solamente te interesa invocar un metodo sin guardar el valor de retorno, y le pasas argumentos simples, puedes omitir los parentesis.

No puedes omitirlos en metodos sin argumentos porque entonces se busca un getter de una propiedad. objeto.toString se convierte en objeto.getToString() por eso no jala; necesita ser objeto.toString().

El punto no es opcional, debe ser objeto.metodo siempre. En el caso de println, ese metodo lo tiene la clase GroovyObject, que es la raiz de todos las clases en Groovy. Cuando haces un programa de una linea con println "hola" todo eso se termina encapsulando en una clase con el nombre del script y ese codigo se inyecta en el metodo estatico main, por eso funciona.

Vientos. Pero entonces cuando

Vientos. Pero entonces cuando quieres guardar el valor si necesitas paréntesis, eso si está extraño. Alguna razón de diseño? O es solamente cose de como lo implementaron?

Encontré que esta situación

Encontré que esta situación es un efecto de implementación más que de diseño y se quiere corregir y aumentar para Groovy 1.8.

En esta propuesta además de hacer los paréntesis opcionales, se van a hacer también los puntos opcionales ( similar a Scala )

http://docs.codehaus.org/display/GroovyJSR/GEP+3+-+Command+Expression+ba...

Imagen de ezamudio

paréntesis

La verdad ni me he fijado bien en todos los casos que se puedan omitir los paréntesis, porque yo prefiero usarlos. Y aunque hagan opcional el punto, lo seguiré usando.

A mi no me late mucho... pero

A mi no me late mucho... pero la idea es poder escribir cosas como estas:

select from: users where age > 32 and sex == 'male'

Que sería equivalente a:

select(from: users).where(age > 32).and(sex == 'male')

Mi desencanto con esto ( a pesar de que se ve super bien ) es que al hacer el lenguaje más y más grande, se vuelve más difícil de dominar por todas los diferentes modos que hay. El otro extremo ( Java , C por ejemplo ) es monótono pero fácil de dominar. No hay sorpresas ni cosas inesperadas, aunque el precio a pagar es que se tienen que escribir todo explicitamente.

¿Es bueno el desempeño de Groovy?

Es que hace rato tuve un conocido que me dijo que Groovy está chido, bonito, si vienes de Java no hay tanta bronca, etc. Pero que es (o era) muy muy lento y para constatar esto me encontré con esto otro y me dije que era tiempo de esperar a que estuviera más maduro el proyecto.

¿Ahora cómo anda Groovy?¿Comparable con Python o Ruby en cuánto a desempeño?

Hay que medir.

Es muy difícil hacer un benchmark bueno que de resultados contundentes y definitivos, pero no se pierde nada intentando alguno que no sea taan bueno ( como el que mencionas ) pero hay que tener en cuenta que eso no se puede tomar como referencia y decir "este es más lento que aquel", por que siempre se tendra que X es más lento que Y para el programa Z con la versión N en el procesador M y demás.

En términos generales, los lenguajes con tipeo dinámico son más lentos que los que tienen tipeo estático, pero también depende de la implementación de ese lenguaje ( por ejemplo Ruby 1.8 clásico es más lento que JRuby en la misma versión, aunque el código sea identico ) Y de para que lo necesitas? Necesitas cada nano segundo que el procesador te pueda dar? Te puedes dar el lujo de perder 1 segundo cada millon de operaciones?

Más importante aún es hacer una implementación buena ( por ejemplo si se necesita un catalogo de 40 elementos, no ir por él a la base de datos siempre y mejor guardarlo en memoria ) y no pelearse con las microoptimizaciones ( si cambiando toda una funcion se reduce de 0.4 ms a 0.2 ms ).

Lo que puedes hacer, es crear un programa sencillo pero que sea intenso en los tres lenguajes y correrlo varias veces y medirlo. Eso te dará una idea pero no será contundente.

Ahí nos platicas los resultados. :)

Imagen de Shadonwk

seria interezante lo del

seria interezante lo del programita, anotado en mi lista de tareas pendientes por hacer (que casi nunca hago) pero si encuentro algo que se tarde un poco en java le mido el tiempo, lo reprodusco en groovy mido el tiempo y pego los resultados...

Imagen de ezamudio

Performance

Se supone que Groovy es más lento que Java, aunque sea compilado. Una razón muy simple es por ejemplo esto:

objeto.metodo()

En Java, se busca el método en la clase a la que pertenece el objeto, y se va buscando hacia arriba en su jerarquía. Si no se encuentra ese método, simplemente no compila el código. En Groovy ese código sí compila, pero se traduce a una búsqueda del método en tiempo de ejecución; si el objeto no implementa o hereda ese método, entonces se busca en la metaclase del mismo y si no se encuentra ahí entonces ya se arroja una excepción en tiempo de ejecución.

Si quieres mejorar un poco el desempeño de un programa en Groovy, entonces cuando quieres ahorrarte toda esa búsqueda en tiempo de ejecución, agregas un ampersand al principio del método.

objeto.&metodo()

Eso hace que solamente se busque el método ya implementado en la clase (o heredado), no se busca en la metaclase.

PERO...

Parece que han hecho optimizaciones al runtime de Groovy porque acabo de probar invocaciones a métodos que no existen en String y en una clase que yo mismo defino en Groovy, y el tiempo es menor si no uso el ampersand:

String x = "prueba"

class Prueba {
  void cacaa(String arg1, Object arg2) {}
}

long t0, t1

try {
  t0 = System.currentTimeMillis()
  x.caca()
} catch (Exception ex) {
  t1 = System.currentTimeMillis()
  println "x.caca() ${t1-t0}"
}

try {
  t0 = System.currentTimeMillis()
  x.&caca()
} catch (Exception ex) {
  t1 = System.currentTimeMillis()
  println "x.&caca() ${t1-t0}"
}

Prueba p = new Prueba()

try {
  t0 = System.currentTimeMillis()
  p.caca()
} catch (Exception ex) {
  t1 = System.currentTimeMillis()
  println "p.caca() ${t1-t0}"
}

try {
  t0 = System.currentTimeMillis()
  p.&caca()
} catch (Exception ex) {
  t1 = System.currentTimeMillis()
  println "p.&caca() ${t1-t0}"
}

Si ejecutas lo anterior, verás que el tiempo es menor para la invocación sin ampersand, al menos para el String. Para la clase Prueba varía muy poco y casi siempre es igual, seguramente porque tiene muy pocos métodos y la búsqueda no tarda nada (habría que hacer que Prueba extienda una clase más compleja, o ponerle muchos métodos para ver qué pasa). Esto es igual si se compila o se interpreta. Si haces las invocaciones en un ciclo (simplemente hay que rodear todo el código a partir de las declaraciones de los longs con algo como 10.times {...}), verás que solamente la primera invocación es la que saca esas diferencias, posteriormente el tiempo baja prácticamente a 0; si en vez de System.currentTimeMillis() usas System.nanoTime() ya verás una diferencia siempre, pero verás que no es muy significativa.

Y al final siempre llegamos a los mismos argumentos: ¿qué es más caro? Desarrollar un sistema en mucho menos tiempo (y hablo de codificar, probar, corregir, integrar, etc etc) y tener que invertir en mejor hardware porque corre algo lento, o desarrollar un sistema en mucho más tiempo (porque lo haces en C o C++ donde es más complicado, tedioso y tardado codificar, compilar, probar, corregir, etc) y que el sistema corra en hardware más modesto porque tiene un muy buen desempeño?

Actualmente yo tengo un sistema ya de tamaño considerable (250 KLOC) hecho en Java. El sistema funciona y por lo tanto no tiene caso reescribirlo nada más porque sí; sin embargo, mucho del código que tengo, si lo paso a Groovy sé que va a terminar siendo más compacto (en una primera fase de migración) y después todavía más compacto y con un diseño distinto en cuanto a interfaces, componentes, jerarquías, etc (en una segunda fase, haciendo ya cambios más drásticos para aprovechar más características de Groovy como closures, metaprogramación, etc). Para hacer programas tipo cronjobs que necesitan usar algo de la lógica de este sistema, estoy usando Groovy y el tiempo de desarrollo y pruebas se reduce de manera dramática. Si me llegara a encontrar con una parte del código que necesita mucha optimización, tal vez lo haría en Java, para tener un poco mejor desempeño; pero la diferencia ya es muy poca, así que solamente valdría la pena para algún algoritmo complejo que se ejecuta miles y miles de veces por minuto; y aún así, en mi experiencia, si tienes un algoritmo que por ejemplo se tarda 5 segundos en ejecutar, para reducirlo a 2 ó 3 segundos, las optimizaciones que le tienes que hacer para bajar el tiempo, son independientes del lenguaje que estás usando, por lo tanto importa más que lo modifiques en el mismo lenguaje a que si simplemente compilas esa parte en Java puro en vez de tenerla en Groovy.

Imagen de ezamudio

comparación

En cuanto a comparar Groovy con Ruby o Python, honestamente no me interesaría tanto el resultado del benchmark; el performance de Groovy hay que compararlo contra el de Java, y se debe optimizar Groovy hasta que tenga el mismo performance que Java. Finalmente Groovy es un lenguaje que corre en la JVM, de modo que las comparaciones de Groovy con Ruby/Python deben arrojar los mismos resultados que comparaciones de Java contra Ruby/Python.

Regresando al punto del performance del programador y no del código ejecutable, la comparación de Groovy contra otros lenguajes debe tomar en cuenta que en Groovy tienes a tu disposición todo el software hecho en Java. Sé que en Ruby y Python también ya hay varias bibliotecas y frameworks disponibles para muchas tareas muy diversas, pero dudo que le lleguen al tamaño de lo que hay en Apache, Spring, etc.

@Shadownk Puedes tomar el

@Shadownk Puedes tomar el microbenchmark que hicimos del reemplazo de L por XX y ver que sale con Groovy.

Imagen de greeneyed

Lo de que Groovy siempre es

Lo de que Groovy siempre es más lento que Java... depende de para que: http://www.jroller.com/greeneyed/entry/separating_concerns_business_logi...

Medir el rendimiento puro en según que operaciones y condiciones, microbenchmarking, es irrelevante para las aplicaciones del mundo real. Hay que hacer las pruebas para el caso en concreto.

Dicho esto, por aprender lenguajes que no sea :). Para la tesis de mi ultimo master probé 10 lenguajes diferentes y unas 14 versiones diferentes, y no veas lo bien que va para quitarte complejos y prejuicios.

A mi personalmente Groovy me gusta mucho, aunque para según qué sigo prefiriendo Java.

S!

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">