Funciones de Julia

Una función es un grupo de declaraciones que ejecutan una tarea juntas.

En Julia, una función es un objeto que asigna una tupla de valores de argumentos a un valor de retorno.

En Julia, se utilizafunctionpara definir funciones, la sintaxis básica es:

function functionname(args)
   expression
   expression
   expression
   ...
   expression
end

De forma predeterminada, el valor que devuelve una función es el valor de la última expresión evaluada, por lo que vemos que arriba no hayreturndeclaración, por supuesto, si se usareturnpalabra clave, la función retornará inmediatamente:.

Ejemplo

julia> function f(x,y)
           x + y
       end
f (generic function with 1 method)
julia> f(2,3)
5

julia> function bills(money)
      if money < 0
         return false
      else
         return true
      end
   end
bills (generic function with 1 method)

julia> bills(50)
true

julia> bills(-50)
false

Si una función necesita devolver múltiples valores, puede usar una tupla:

Ejemplo

julia> function mul(x,y)
                  x+y, x*y
               end
mul (generic function with 1 method)

julia> mul(5, 10)
(15, 50)

Cuando una función tiene solo una expresión, puede omitirfunctionpalabra clave, en el lado izquierdo del signo igual se establece el nombre de la función y los parámetros, y en el lado derecho la expresión, similar a una asignación:

julia> f(x,y) = x + y
f (generic function with 1 method)

Sin paréntesis, la expresiónfse refiere al objeto de función, que puede pasarse como cualquier valor:

julia> g = f;
julia> g(2,3)
5

Ejemplo

julia> f(a) = a * a
f (generic function with 1 method)

julia> f(5)
25

julia> func(x, y) = sqrt(x^2 + y^2)
func (generic function with 1 method)

julia> func(5, 4)
6.4031242374328485

Al igual que los nombres de variables, los caracteres Unicode también pueden usarse como nombres de funciones:

julia> ∑(x,y) = x + y
∑ (generic function with 1 method)

julia> ∑(2, 3)
5

Tipo de retorno

Podemos usar el::operador para especificar el tipo de retorno de la función.

Ejemplo

julia> function g(x, y)::Int8
           return x * y
       end;

julia> typeof(g(1, 2))
Int8

Los ejemplos de funciones anteriores ignoran los tipos de x e y y devuelven un valor de tipo Int8.

Parámetros opcionales

En las funciones podemos establecer valores predeterminados para los parámetros, de modo que cuando no se proporciona el parámetro, se puede usar el valor predeterminado para calcular:

El siguiente ejemplo define la función pos con tres parámetros, donde el parámetro cz tiene un valor predeterminado de 0, por lo que al llamar a la función, este parámetro puede omitirse:

Ejemplo

julia> function pos(ax, by, cz=0)
         println("$ax, $by, $cz")
      end
pos (generic function with 2 methods)

julia> pos(10, 30)
10, 30, 0

julia> pos(10, 30, 50)
10, 30, 50

Parámetros de palabra clave

A veces, algunas funciones que definimos requieren muchos parámetros, pero llamarlas puede ser engorroso, porque podríamos olvidar el orden de los parámetros. Por ejemplo:

function foo(a, b, c, d, e, f)
...
end

Podríamos olvidar el orden de los parámetros y ocurriría la siguiente situación al llamar a la función:

foo("25", -5.6987, "hello", 56, good, 'ABC')
o 
foo("hello", 56, "25", -5.6987, 'ABC', good)

Esto se ve muy confuso.

Los parámetros de palabra clave de Julia permiten identificar los parámetros por nombre en lugar de solo por posición, lo que hace que estas funciones complejas sean fáciles de usar y ampliar.

Para marcar parámetros con palabras clave, se debe usar un punto y coma después de los parámetros no marcados de la función;y a continuación, uno o más pares clave-valorkey=value, como se muestra a continuación:

Ejemplo

julia> function foo(a, b ; c = 10, d = "hi")
         println("a is $a")
         println("b is $b")
         return "c => $c, d => $d"
      end
foo (generic function with 1 method)

julia> foo(100,20)
a is 100
b is 20
"c => 10, d => hi"

julia> foo("Hello", "Ejemplo", c=pi, d=22//7)
a is Hello
b is Ejemplo
"c => π, d => 22//7"

Con los parámetros de palabra clave, la posición de los parámetros ya no es tan importante. La función anterior también se puede llamar así:

Ejemplo

julia> foo(c=pi, d =22/7, "Hello", "Ejemplo")
a is Hello
b is Ejemplo
"c => π, d => 3.142857142857143"

Funciones anónimas

Una función anónima es una función sin nombre.

Las funciones anónimas se declaran dinámicamente en tiempo de ejecución. Aparte de no tener nombre, son iguales a las funciones estándar.

En Julia, las funciones anónimas se pueden usar en muchos lugares, por ejemplo, map() y la comprensión de listas.

Al usar funciones anónimas, nuestro código se vuelve más conciso.

La sintaxis de las funciones anónimas usa el símbolo->。

Ejemplo

julia> x -> x^2 + 2x - 1
#1 (generic function with 1 method)

julia> function (x)
           x^2 + 2x - 1
       end
#3 (generic function with 1 method)

El ejemplo anterior crea una función que acepta un parámetroxy devuelve el polinomio del valor actualx^2+2x-1de la función.

El uso principal de las funciones anónimas es pasarlas a funciones que reciben funciones como parámetros. Un ejemplo clásico es map, que aplica una función a cada elemento de un array y luego devuelve un nuevo array que contiene los valores resultantes:

Ejemplo

julia> map(round, [1.2, 3.5, 1.7])
3-element Vector{Float64}:
 1.0
 4.0
 2.0

Si la función de transformación que se pasa a map como primer parámetro ya existe, no hay problema en usar directamente el nombre de la función. Pero normalmente la función que se quiere usar aún no está definida, por lo que usar una función anónima es más conveniente:

Ejemplo

julia> map(x -> x^2 + 2x - 1, [1, 3, -1])
3-element Vector{Int64}:
  2
 14
 -2

Para escribir una función anónima que acepte múltiples parámetros, se puede usar la sintaxis (x,y,z)->2x+y-z, mientras que una función anónima sin parámetros se escribe ()->3. Esta forma de escribir una función sin parámetros puede parecer un poco extraña, pero es necesaria para el cálculo diferido. Este uso envuelve un bloque de código en una función sin parámetros y luego lo invoca como f.

Por ejemplo, considere la llamada a get:

Ejemplo

get(dict, key) do
    # default value calculated here
    time()
end

El código anterior equivale a llamar a get con una función anónima que contiene el código. Está encerrado entre do y end, como se muestra a continuación:

get(()->time(), dict, key)

Aquí, la llamada a time se retrasa mediante una función anónima sin parámetros que la envuelve. Esta función anónima solo se invoca cuando a dict le falta la clave solicitada.


Anidamiento de funciones y recursividad

En Julia, las funciones pueden anidarse.

El siguiente ejemplo anida una función add1 dentro de la función add():

Ejemplo

julia> function add(x)
         Y = x * 2
         function add1(Y)
           Y += 1
         end
         add1(Y)
       end
add (generic function with 1 method)

julia> d = 10
10

julia> add(d)
21

Del mismo modo, las funciones en Julia también pueden ser recursivas.

La recursividad se refiere al método de usar la propia función dentro de su definición.

Por ejemplo:
"Había una vez una montaña, en la montaña había un templo, en el templo había un monje anciano que le contaba una historia a un monje joven. ¿Cuál era la historia? 'Había una vez una montaña, en la montaña había un templo, en el templo había un monje anciano que le contaba una historia a un monje joven. ¿Cuál era la historia? "Había una vez una montaña, en la montaña había un templo, en el templo había un monje anciano que le contaba una historia a un monje joven. ¿Cuál era la historia? ..."'"

A continuación usamos el operador ternario para probar la recursividad. El operador ternario opera sobre tres operandosexpr ? a : b, si expr es true, el valor es el resultado de evaluar a; de lo contrario, el resultado de evaluar b.

Ejemplo

julia> sum(x) = x > 1 ? sum(x-1) + x : x
sum (generic function with 1 method)

julia> sum(10)
55

El ejemplo anterior se usa para calcular la suma de todos los números hasta un número entero, incluido ese número. En esta recursividad, hay un caso base: cuando x es 1, ese valor se devuelve.

El ejemplo más famoso de recursividad es calcular el n-ésimo número de Fibonacci. La secuencia de Fibonacci se refiere a la secuencia 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368........

A partir del tercer término, cada término de esta secuencia es igual a la suma de los dos anteriores.

Ejemplo

julia> fib(x) = x < 2 ? x : fib(x-1) + fib(x-2)
fib (generic function with 1 method)

julia> fib(10)
55

julia> fib(20)
6765

Map

El formato de definición de Map es el siguiente:

map(func, coll)

Aquí, func es una función que se aplica sucesivamente a cada elemento de la colección coll. Map generalmente contiene una función anónima y devuelve una nueva colección.

Ejemplo

julia> map(A -> A^3 + 3A - 3, [10,3,-2])
3-element Array{Int64,1}:
 1027
   33
  -17

Filter

El formato de definición de Filter es el siguiente:

filter(function, collection)

La función filter devuelve una copia de la colección y elimina los elementos para los cuales el resultado de llamar a la función es false.

Ejemplo

julia> array = Int[1,2,3]
3-element Array{Int64,1}:
 1
 2
 3
 
julia> filter(x -> x % 2 == 0, array)
1-element Array{Int64,1}:
 2
Otras extensiones