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

Groovy:comparativa con otros lenguajes

Hace tiempo que estoy tratando de aprender este lenguaje y la verdad todavía no le "agarro la onda". Y creo que la única forma es perder el miedo a conocer algo nuevo.

Pero, antes de empezar ¿Qué es Groovy?

Según San Google, es un lenguaje de programación implementado sobre la plataforma Java y que sigue el paradigma orientado a objetos.

Algunas de sus características:

  • Compatible con programas en Java
  • Dependiente de la Java Virtual Machine (JVM)
  • Genera bytecodes al igual que Java
  • Bueno, bonito y barato(más bien gratuito)
  • Bastante parecido a Python, Scala y Ruby

Un ejemplo sencillo: "El famoso hola mundo"

Hola.groovy:

println "Hola mundo, yo uso Groovy"

Hola.py:

println "Hola  mundo, yo uso Python"

Hola.rb:

puts "Hola  mundo, yo uso Ruby"

Hola.scala:

println ("Hola  mundo, yo uso Scala")

Es increible lo parecidos que son, sin embargo cada uno tiene su propias peculiaridades.

También me llama la atención que las clases (class) son un tanto extrañas (según yo), se puede omitir el ";" , se pueden emplear librerías Java import java.paquete.clase;entre otras cosas.

Otros ejemplos ahora con clases:

Gente.groovy

class Gente{
   String Nombre

   def Nombre(){
       println Nombre
   }

  static void main (String[] args){
    def miObjeto= new Gente(Nombre: 'El Negativo’)
    miObjeto.Nombre()
  }

}

Gente.py:

class Gente:
    def asignaNombre(self,nombre):
        self.nombre
    def obtenerNombre(self):
        return self.nombre

miObjeto = Gente()
miObjeto.asignaNombre(‘El Negativo’)
print “Nombre ”, miObjeto.obtenerNombre()

Gente.rb:

class Gente

  def initialize(nombre)
    @nombre=nombre
  end

  def nombre
    @nombre
  end

  def to_s
    “#{@nombre}”
  end

miObjeto =  Gente.new(‘El Negativo’)
miObjeto.nombre
miObjeto.to_s

Gente.scala:

class Gente(nombre: String)
miObjeto = new Gente
miObjeto.nombre="El Negativo"

Ahora una clase con Java

Java.java

public class Gente{
   String nombre;
   public Gente(String miNombre){
      nombre=minombre;
    }
    public void verGente(){
      System.out.println(Nombre);
    }

    public static void main(String[] args){
      Gente g=new Gente();
      g.verGente();
    }
}

¿Qué más sigue? los Clousures

Según San Google,"es un bloque de código anónimo definido entre llaves"

Algo asi como:

def TuEdad={
     println "Tu tienes 5 años"
}

println "¿Adivina cuantos años tengo?"
TuEdad()

Ustedes perdonaran la calidad de estos programitas, pero no todos somos @ezamudio u @OscarRyz.

Tu...¿Qué harias con Groovy?

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.

Corregí un par de cosas en

Te complemento los ejemplos de los closures:

Python

def a():
   def b():
      print "Tu tienes 5 años"
    return b

c = a()
c()

Ruby

   # sin interprete a la mano para confirmar esto
   a =  -> {
     "tu tienes 5 años"
   }
   a.call

Scala

val t = ()=> print( "Tu tienes 5 años")
t()

Java

Runnable r = new Runnable() {
     public void run() {
          System.out.println("Tu también tienes 5 años");
      }
};
r.run();

Y porque no:

Ryz

b = (){
    out.println("Tienes 5")
}
b()

Gente y hola mundo:

gente.Gente {
   nombre : String
   verGente() {
      out.println( nombre )
   }
   __ main( args : String* ) {
      g = Gente()
      g.nombre = "Ryz"
      g.verGente()
   }
}
hola.Mundo {
   ___ main(args : String* ) {
      out.println("Hola, mundo")
   }
}

Diablos creo que ya me tengo que poner a trabajar de nuevo en eso.

Imagen de ezamudio

JVM

También me llama la atención que las clases (class) son un tanto extrañas (según yo), se puede omitir el ";" , se pueden emplear librerías Java import java.paquete.clase;entre otras cosas.

Eso es porque Groovy corre sobre la JVM. Si compilas el código groovy, se compila a bytecode de Java, te queda un .class y puedes correrlo en Java solamente importando dos o tres jars que requiere groovy.

Haz la prueba, crea un archivo Ejemplo.groovy con este código (NO le vayas a poner Prueba.groovy, luego verás por qué):

class Prueba {
  String nombre
}

Prueba p1 = new Prueba()
p1.nombre = 'Uno'
Prueba p2 = new Prueba(nombre:"Prueba Dos creada a las ${new Date()}")
println p1.nombre
println p2.nombre

Si lo corres, obtendrás algo así:

$ groovy Ejemplo.groovy 
Uno
Prueba Dos creada a las Thu Apr 07 17:09:59 CDT 2011

Pero eso fue interpretando el archivo como un script de Groovy. Ahora compílalo con groovyc:

$ groovyc Ejemplo.groovy
$ ls *.class
Ejemplo.class	Prueba.class

Como puedes ver, de un solo archivo, se crearon dos clases. Así es: Groovy te permite definir varias clases en un archivo. Y no son clases internas ni nada de eso, cada una es clase de primer nivel. Puedes analizarlas con javap:

$ javap Ejemplo

Compiled from "Ejemplo.groovy"
public class Ejemplo extends groovy.lang.Script{
    public static java.lang.Long __timeStamp;
    public static java.lang.Long __timeStamp__239_neverHappen1302214244561;
    public Ejemplo();
    public Ejemplo(groovy.lang.Binding);
    public static void main(java.lang.String[]);
    public java.lang.Object run();
    public java.lang.Object this$dist$invoke$4(java.lang.String, java.lang.Object);
    public void this$dist$set$4(java.lang.String, java.lang.Object);
    public java.lang.Object this$dist$get$4(java.lang.String);
    protected groovy.lang.MetaClass $getStaticMetaClass();
    public static void __$swapInit();
    static {};
    public java.lang.Object super$3$getProperty(java.lang.String);
    public java.lang.String super$1$toString();
    public void super$3$setProperty(java.lang.String, java.lang.Object);
    public void super$1$notify();
    public void super$3$println();
    public void super$1$notifyAll();
    public void super$3$print(java.lang.Object);
    public void super$3$printf(java.lang.String, java.lang.Object[]);
    public java.lang.Object super$1$clone();
    public java.lang.Object super$3$evaluate(java.lang.String);
    public void super$1$wait();
    public groovy.lang.MetaClass super$2$getMetaClass();
    public void super$1$wait(long, int);
    public void super$2$setMetaClass(groovy.lang.MetaClass);
    public java.lang.Class super$1$getClass();
    public groovy.lang.Binding super$3$getBinding();
    public void super$1$finalize();
    public void super$3$printf(java.lang.String, java.lang.Object);
    public void super$3$setBinding(groovy.lang.Binding);
    public void super$1$wait(long);
    public void super$3$run(java.io.File, java.lang.String[]);
    public java.lang.Object super$3$evaluate(java.io.File);
    public void super$3$println(java.lang.Object);
    public boolean super$1$equals(java.lang.Object);
    public java.lang.Object super$3$invokeMethod(java.lang.String, java.lang.Object);
    public int super$1$hashCode();
    static java.lang.Class class$(java.lang.String);
}

Y la otra clase también:

$ javap Prueba
Compiled from "Ejemplo.groovy"
public class Prueba extends java.lang.Object implements groovy.lang.GroovyObject{
    public static java.lang.Long __timeStamp;
    public static java.lang.Long __timeStamp__239_neverHappen1302214244480;
    public Prueba();
    public java.lang.Object this$dist$invoke$2(java.lang.String, java.lang.Object);
    public void this$dist$set$2(java.lang.String, java.lang.Object);
    public java.lang.Object this$dist$get$2(java.lang.String);
    protected groovy.lang.MetaClass $getStaticMetaClass();
    public groovy.lang.MetaClass getMetaClass();
    public void setMetaClass(groovy.lang.MetaClass);
    public java.lang.Object invokeMethod(java.lang.String, java.lang.Object);
    public java.lang.Object getProperty(java.lang.String);
    public void setProperty(java.lang.String, java.lang.Object);
    public static void __$swapInit();
    static {};
    public java.lang.String getNombre();
    public void setNombre(java.lang.String);
    public void super$1$wait();
    public java.lang.String super$1$toString();
    public void super$1$wait(long);
    public void super$1$wait(long, int);
    public void super$1$notify();
    public void super$1$notifyAll();
    public java.lang.Class super$1$getClass();
    public java.lang.Object super$1$clone();
    public boolean super$1$equals(java.lang.Object);
    public int super$1$hashCode();
    public void super$1$finalize();
    static java.lang.Class class$(java.lang.String);
}

Si hacemos una clase similar en Java (pero no tendría el constructor default que agrega Groovy como el que usamos para la segunda instancia):

public class Prueba2 {
  private String nombre;
  public void setNombre(String value) {
    nombre = value;
  }
  public String getNombre() {
    return nombre;
  }
}
$ javap Prueba2
Compiled from "Prueba2.java"
public class Prueba2 extends java.lang.Object{
    public Prueba2();
    public void setNombre(java.lang.String);
    public java.lang.String getNombre();
}

Ahora, regresando a Groovy, para correr el ejemplo que hiciste en Groovy pero con java:

$ java Ejemplo
Exception in thread "main" java.lang.NoClassDefFoundError: groovy/lang/Script
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
...blabla...

Tienes que hacer algo así:

$ java -cp $GROOVY_HOME/embeddable/groovy-all-1.7.10.jar:. Ejemplo
Uno
Prueba Dos creada a las Thu Apr 07 17:17:26 CDT 2011

O si no quieres usar ese jar que tiene varias cosas adicionales que tal vez no necesitas, entonces:

$ java -cp $GROOVY_HOME/lib/groovy-1.7.10.jar:$GROOVY_HOME/lib/asm-3.2.jar:. Ejemplo
Uno
Prueba Dos creada a las Thu Apr 07 17:18:37 CDT 2011

Son los dos jars que he visto que se necesitan, no sé si para cosas más complejas se necesite algo más. Tal vez para ciertas cosas más avanzadas del lenguaje, se requieran otras bibliotecas, pero incluso usando closures, con esas dos la haces. Eso es muy útil para poder integrar clases Groovy a aplicaciones Java, afectando de manera mínima las dependencias de dicha aplicación.

Imagen de Sr. Negativo

Deberían ser maestros de programación

Solo falta que sus códigos cobren vida y tengan voluntad propia. No ya en serio, muy buena explicación del lenguaje. Yo apenas voy aprendiendo un poco.

 
def TuEdad={
     println "Ahora tengo 10 años"
}

println "¿Adivina cuantos años tengo?"
TuEdad()

Me falta investigar más sobre los Clousures Gracias por las aclaraciones.

Imagen de ezamudio

Closures

Piensa en los closures como funciones que se pueden pasar como parámetros a métodos o a otros closures. Lo que ni a mi me queda todavía muy claro es el contexto del cual pueden tomar variables, pero por ahora no nos compliquemos con eso. La diferencia entre un closure y un método, es que el closure no está pegado a un objeto, es más similar a una función como de lenguaje procedural. Los closures tienen un valor de retorno (indefinido) y pueden recibir parámetros.

//Este es el closure mas simple
def c1 = {
        println "hola"
}

//Este es un closure simple con un parametro
def saluda = { nombre ->
        println "Hola, $nombre"
}

//Este closure espera recibir como parametros un closure y una cadena
def c3 = { algo, nombre ->
        algo(nombre)
}

def despide = { nombre ->
        println "Adios, ${nombre}"
}

c1()
saluda("Negativo")
despide("Positivo")
//Esto hace lo mismo que las dos lineas anteriores
c3(saluda, "Negativo")
c3(despide, "Negativo")
//Ahora vamos a pasar el closure a unas listas
//El metodo each() de la lista toma un closure como parametro y lo invoca
//con cada elemento de la lista, pasando el elemento como parametro
["benek", "oscarryz", "ezamudio"].each saluda
//se puede llamar con o sin parentesis
//Y ademas each devuelve la lista al final
println( ["wishmaster", "java.daba.doo"].each(despide))

//La lista es un buen ejemplo para closures porque tiene varios metodos para ellos
//Si el closure no declara parámetros, tendrá uno implícito llamado "it"
println( ['a', 'b', 'C', 'd', 'E', 'f'].collect { Character.isUpperCase(it.charAt(0)) } )
println( ['a', 'b', 'C', 'd', 'E', 'f'].findAll { Character.isUpperCase(it.charAt(0)) } )
println( ['a', 'b', 'C', 'd', 'E', 'f'].find { Character.isUpperCase(it.charAt(0)) } )
println( [1,2,3,4,5].collect { it * 2 } )
//Esto suma todos los elementos
println( [1,2,3,4,5].inject(0) { it, prev -> it + prev } )

Imagen de domix

Algunos videos

Si quieren pueden el siguiente video en donde se hace una introducción al lenguaje:

Introducción a Groovy from Grails.org.mx on Vimeo.

Y en este otro se habla un poco mas de Closures

Ciclos en Groovy y Colecciones from Grails.org.mx on Vimeo.

Imagen de AlexSnake

Mas comentarios...

Bueno a mi me interesaría aprender más sobre este lenguaje y claro por supuesto también de los otros que mencionan, de hecho no sabía que existían esos lenguajes y mucho menos que es programación implementado para la plataforma java hasta que me registre en este foro y fui leyendo los temas que exponen. Pero muchos como yo no sabemos ni cómo debemos compilar un "hola mundo" aun que hicieron el favor de poner como es la clase completa, intente ponerla en una clase normal de java desde eclipse y claro me arrojo los errores de sintaxis.

Entonces qué tipo de archivo debo abrir, se requieren algún jar en especifico? Y también me llama mucho la atención que no hay mucha fuente de trabajo para estos lenguajes, estuve buscando ofertas de trabajo donde soliciten la experiencia en estos lenguajes y realmente son muy escasas la vacantes que encontré.

Yo incursione en esta carrera por obras del destino porque realmente mi intención era estudiar otra cosa pero le he tomado el gusto y estoy viviendo de esto, pero que ventaja hay en aprender estas variantes si no hay una demanda como lo es java normalito.

Re: Corregí un par de cosas en

Creo que esa manera de llamar closures en Ruby aplica para la serie 1.9.x; en Ruby legacy (y creo todavía soportado) es :

#lambda nos ayuda a no tener que aprender
#el ->, ni bronquearte con los yield en cosas
#faciles, además parecido a python
cosa = lambda { |parametro1, parametro2|
----puts "Parametro 1 vale #{parametro1} \n Parametro 2 vale #{parametro2}"
}

#de ahí basta con
cosa.call("Chachito", "caramelo")

Te faltaron también closures en JavaScript:

funcioncita = function(e){
----alert("El valor de e es " + e);
}

Y ya que andamos por estos rumbos les aporto las de python:

#En python existen 2 maneras, con funciones
#lambda o funciones previamente definidas
x = lambda z: z ** 2

#O también
def funcionera(cosa="NoCosa"):
----if(cosa == "NoCosa"):
--------print ("No parametrasteSS nada compadre!")
----else:
--------print ("La cosa que parametrasteSS es", cosa)

#Aquí asignas el "closure"
f = funcionera

#Aqui lo llamas
f("Shalalalala")
#O también
f()

Y pues en Java los closures no existen se llaman implementaciones (para lo que necesitas definir una interface, ¿o estoy mal?), porqué a fin de cuentas es lo que hiciste usar una interface que no viene siendo otra cosa más que pasar por "argumento" un método u acción.

¿Ese código ya será el definitivo pa Ryz?...Si es así que chido, pero cómo sugerencia estaría chido que quitaras ese "__main(args : String*)", o sea el asterisco que sigue al tipo del parámetro, por poco me espanto y creo que es un puntero XD...y creo que a más de uno nos pasaría (cómo me está pasando con ObjC).

¬¬, me mandaron cómo

¬¬, me mandaron cómo duplicado un comentario al editarlo!!!

La corrección es en Python:

def a():
----print "Hola mundo"

closure = a

#Es algo raro regresar la referencia a una función dentro de otra función.
#De hecho es redundante.

Y en ruby hay otra forma, con lambda:

cosa = lambda{|param|
----puts "El parametro trae #{param}"
}

cosa.call("Un valor")

Tengo una duda con Ryz, ¿porqué depués del tipo de parámetro a recibir pones un *?; eso me aterra y recuerda a los punteros en C. ¿O tienen alguna notación especial?.

Re: Mas comentarios...

Estos lenguajes muchas veces son complemento de Java y ayudan a extender o facilitar funcionalidades. Por ejemplo, con Groovy, Scala, Jython y JRuby puedes usar las closures y compilando directo a Java.

¿Quieres desarrollar en Web sin complicarte tanto la vida, pero necesitas utilizar el Tomcat?... Para esto tienes de nuevo a Groovy, Jython y JRuby. Donde puedes utilizar los frameworks de estos lenguajes SIN de cambiar tu plataforma.

¿Quieres agregar a tu proyecto actual algo de programación funcional? Sin mover TODA tu plataforma, usas Scala o Jython y listo (no sé si Groovy sea funcional).

En fin, yo diría que está chido aprenderlos, porqué te dan las facilidades y librerías que tiene java + características específicas de algún lenguaje de programación.

El String*, espero que sí ,

El String*, espero que sí , creo que lo copié de Python o de Ruby donde String* es como "0 o muchos Strings" es decir, el equivalenta en Java a varargs en Java String ... args y digo creo, porque no recuerdo a quien se lo copie exactamente.

Imagen de benek

String*

El String* yo lo he visto en Scala.

class Upper {
  def upper(strings: String*): Seq[String] = {
    strings.map((s:String) => s.toUpperCase())
  }
}

val up = new Upper
Console.println(up.upper("A", "First", "Scala", "Program"))

Ahh si , entonces fue de

Ahh si , entonces fue de Scala :P en Ruby es *thing

Python y ruby lo manejan pero

Python y ruby lo manejan pero es aplicado al parámetro no al tipo (bueno, si el tipado dinámico y eso), creo que para tu caso quedaría y es antes del nombre:

hola.Mundo {
   ___ main(*args : String ) {
      out.println("Hola, mundo")
   }
}

Y me gustó mucho el estilo pythonico del private con ___[espacio]metodoNombre. Ryz parece que en cuanto tenga las primeras versiones tendrá varios adeptos.

El scope de variables en las

El scope de variables en las closures (al menos en Ruby y Python) depende en donde lo defines, si éstas reciben parámetros y estás dentro de una clase persona, si tienes un parámetro llamado nombre y dentro del closure te refieres a nombre, pues te refieres al parámetro; de lo contrario te refieres al de la clase o scope que estes manejando (mientras sea alcanzable).

Imagen de pavul

mas dudas

a mi me gustaria saber si Groovy es Grails, porque me parece que empece un libro de y me empezo a explicar de Grails.

hacia donde se enfoca Groovy, hacia facilitar o ser un complemento de lenguaje de programacion?

no es mas dificil aprender un lenguaje nuevo con todo lo que conyeva en vez de buscar la manejra en java?

Imagen de ezamudio

preguntas...

Son varias preguntas pavul...

Groovy no es Grails. Grails es un framework hecho en Groovy, para desarrollo web. Groovy es un lenguaje de programación de tipado dinámico, para la JVM, con capacidades de scripting y otras monerías; no es un complemento de lenguaje, es un lenguaje por sí mismo. Tiene su propio compilador e intérprete. Tiene mucha sintaxis opcional, de manera que puedes escribir código prácticamente idéntico a Java o puedes usar su propia sintaxis.

En cuanto a tu última pregunta: a veces es más difícil hacer algo en Java, que simplemente hacerlo en otro lenguaje. Y si consideras que sólo necesitas aprender ese lenguaje una vez, mientras que ese "algo" en Java no sabes si lo vas a tener que hacer varias veces... y si además te gusta la programación, aprender un nuevo lenguaje generalmente es una experiencia muy grata.

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