martes, 1 de junio de 2021

Power Query: Funciones Recursivas y el Operador de ámbito

Abordaremos hoy uno de esos temas interesantes por su potencial: las funciones recursivas en power Query y el uso de la @ como operador de ámbito.

Tengamos claro que para escribir una función que sea recursiva, será necesario usar el operador de ámbito (@) para hacer referencia a la función dentro de su ámbito.

Para mostrar un ejemplo claro replicaremos la Sucesión de Fibonacci, ejemplo más claro de 'recursividad'.
Recuerda el algortimo de esta sucesión en esta entrada del blog.
La clave de esta sucesión es acumular al valor actual el valor previo... siendo los primeros valores 0 y 1, quedando entonces una secuencia creciente de números enteros naturales donde cada valor es la suma de los dos anteriores así:
0, 1, 1, 2, 3, 5, 8, 13, 21, etc...

Accederemos al editor de Power Query creando una consulta en blanco donde escribiremos la siguiente consulta:
let 
//creamos una lista de cuantos elementos de la Sucesión de Fibonacci queramos mostrar
enteros={1..25},

//Transformamos esos valores 1,2,3,4... de la anterior lista
//con el Algortimo de Fibonacci, esto es, acumulando el valor presente al anterior
//forzando como primeros elementos el 0 y el 1
Fibonacci= List.Transform(enteros, 
    (x) => let Fibo = (n) => 
                if n = 1 then 0 else 
                    if n = 2 then 1 else 
                        //hacemos uso recursivo de la función creada
                        //ya que el siguiente número de la secuencia es la suma de los dos anteriores, para calcular en valor N de la secuencia necesitamos, por tanto, conocer/calcular las posiciones N-1 y N-2
                        ( @Fibo(n-1) + @Fibo(n-2) )
            in 
                Fibo(x) )
in 
    Fibonacci

Power Query: Funciones Recursivas y el Operador de ámbito

Interesante cómo el operador de ámbito (@) aplicada sobre si misma (sobre la función definida 'Fibo') permite obtener ese cálculo buscado...
Sin el operador aplicado obtendríamos un error, ya que no se reconocería (aún) la función 'Fibo', al estar llamándola/utilizándola dentro de sí misma, cuando todavía no está generada.

El resultado es el esperado, una lista con la secuencia de los 25 primeros elementos de la Sucesión de Fibonacci:
Power Query: Funciones Recursivas y el Operador de ámbito


Creo muy curioso comparar las estructuras de programación, para este caso, entre lenguaje M y leguaje VBA del artículo comentado al inicio de este post), del que estraigo la parte relevante:
...
  Dim f0 As Long, f1 As Long, elementos As Integer
f0 = 0: f1 = 1
elementos = 25
'dimensionamos nuestra Array al número de elementos deseados
ReDim Fib(1 To elementos) As Long

'Rellenamos la matriz con los elementos de la Serie de Fibonacci
Fib(1) = f0     'asignamos dato al primer valor
Fib(2) = f1     'asignamos dato al segundo valor
For i = 3 To UBound(Fib)
    Fib(i) = f0 + f1    'Calcula el dato como suma de un elemento más el anterior
    'hacemos la recurrencia para los siguientes elementos
    f0 = f1
    f1 = Fib(i)
Next i
...


Obviamente la base del algoritmo es la misma (sumar un elemento al anterior)...
Pero la recurrencia/recursividad en VBA para Excel la obtenemos con los clásicos bucles: For ...Next, mientras que en nuestro ejercicio la hemos obtenido aplicando el operador de ámbito (@); pero en ambos casos aparecen en el mismo punto..


Es un concepto algo 'retorcido', y sin duda alternativas como List.Acumulate o List.Generate, resuelven la mayoría de las veces esta necesidad que ofrece esta 'recursividad'.

Cosa que veremos en siguientes entradas...

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.