Número y tipo de los parámetros de una clausura

Es posible obtener el número y tipo de parámetros que espera una clausura:
generaciondecodigos@nereida:~/Lgroovy/closures$ cat -n op.groovy
     1  #!/usr/bin/env groovy
     2
     3  def randapply(f) {
     4    random = new Random()
     5
     6    if (f.getParameterTypes().size() == 2) {
     7      x = random.nextInt(50)
     8      y = random.nextInt(50)
     9      println "f($x, $y) = ${f(x, y)}"
    10    }
    11    else {
    12      x = random.nextInt(10)
    13      x *= x
    14      println "f($x) = ${f(x)}"
    15    }
    16  }
    17
    18  randapply { x, y -> x+y }
    19  randapply { Math.sqrt(it) }

Un ejemplo de como utilizar esta información lo a el método each de los maps. Si se le pasan dos parámetros los interpreta como una pareja clave-valor. Si se le pasa uno sólo lo interpreta como un objeto Map.Entry:

generaciondecodigos@nereida:~/Lgroovy/closures$ cat -n creatingandusingclosures.groovy
     1  #!/usr/bin/env groovy
     2
     3  map = [ 'a' : 1, 'b' : 2 ]
     4  println map
     5
     6  map.each { key, val -> map[key] *= 2 }
     7
     8  println map
     9
    10  map.each {  map[it.key] *= 2 }
    11
    12  println map
    13
    14  duplicate = {  map[it.key] *= 2 }
    15
    16  map.each duplicate
    17
    18  println map
    19
    20  def dup(e) {
    21    map[e.key] *= 2
    22  }
    23
    24  map.each this.&dup
    25
    26  println map

El método getParameterTypes tiene la firma:

public Class[] getParameterTypes()

El manual dice:

    Returns an array of Class objects that represent the formal parameter
    types, in declaration order, of the method represented by this Method
    object. Returns an array of length 0 if the underlying method takes
    no parameters.

    Returns:
        the parameter types for the method this object represents

Ejecución:

generaciondecodigos@nereida:~/Lgroovy/closures$ groovy op.groovy
f(39, 24) = 63
f(9) = 3.0
generaciondecodigos@nereida:~/Lgroovy/closures$ groovy op.groovy
f(28, 0) = 28
f(64) = 8.0

Sigue un ejemplo en el que examinamos las firmas de los métodos de una clase:

generaciondecodigos@nereida:~/src/java/reflection$ cat -n GetPar.groovy
     1  import java.lang.reflect.*
     2
     3  class MyClass
     4  {
     5      // Declare the "sample" method - just for testing:
     6      public void sample(int i, float f, double d, String str, byte[] ba)
     7      { }
     8  }
     9
    10  // Declare a Class object:
    11  Class mc = MyClass.class
    12
    13  // Declare an array of methods:
    14  Method[] methArr = mc.getMethods()
    15
    16  // Get the parameter types:
    17  for (i in 0..<methArr.length) {
    18      if ("sample" != methArr[i].getName()) continue
    19      println(methArr[i])
    20      println("The parameter types are:")
    21
    22      // Declare the array of parameter types:
    23      Class[] paramTyArr = methArr[i].getParameterTypes()
    24      k = 1
    25      paramTyArr.each { println("${k++}\t$it") }
    26  }
La ejecución produce la salida:
generaciondecodigos@nereida:~/src/java/reflection$ groovy GetPar.groovy
public void MyClass.sample(int,float,double,java.lang.String,byte[])
The parameter types are:
1       int
2       float
3       double
4       class java.lang.String
5       class [B

Casiano Rodríguez León
2010-04-30