Buscar..


Sintaxis

  • x -> [cuerpo]
  • (x, y) -> [cuerpo]
  • (xs ...) -> [cuerpo]

Observaciones

0.4.0

En versiones anteriores de Julia, los cierres y las funciones anónimas tenían una penalización de rendimiento en tiempo de ejecución. Esta penalización ha sido eliminada en 0.5.

Composición de funciones

Podemos definir una función para realizar la composición de la función utilizando la sintaxis de la función anónima :

f ∘ g = x -> f(g(x))

Tenga en cuenta que esta definición es equivalente a cada una de las siguientes definiciones:

∘(f, g) = x -> f(g(x))

o

function ∘(f, g)
    x -> f(g(x))
end

recordando que en Julia, f ∘ g es simplemente sintaxis de azúcar para ∘(f, g) .

Podemos ver que esta función se compone correctamente:

julia> double(x) = 2x
double (generic function with 1 method)

julia> triple(x) = 3x
triple (generic function with 1 method)

julia> const sextuple = double ∘ triple
(::#17) (generic function with 1 method)

julia> sextuple(1.5)
9.0
0.5.0

En la versión v0.5, esta definición es muy eficaz. Podemos mirar en el código LLVM generado:

julia> @code_llvm sextuple(1)

define i64 @"julia_#17_71238"(i64) #0 {
top:
  %1 = mul i64 %0, 6
  ret i64 %1
}

Está claro que las dos multiplicaciones se han plegado en una sola multiplicación, y que esta función es lo más eficiente posible.

¿Cómo funciona esta función de orden superior? Crea un llamado cierre , que consiste no solo en su código, sino que también realiza un seguimiento de ciertas variables desde su alcance. Todas las funciones en Julia que no se crean en el ámbito de nivel superior son cierres.

0.5.0

Uno puede inspeccionar las variables cerradas a través de los campos del cierre. Por ejemplo, vemos que:

julia> (sin ∘ cos).f
sin (generic function with 10 methods)

julia> (sin ∘ cos).g
cos (generic function with 10 methods)

Implementando Currying

Una aplicación de los cierres es aplicar parcialmente una función; es decir, proporcione algunos argumentos ahora y cree una función que tome los argumentos restantes. Currying es una forma específica de aplicación parcial.

Comencemos con la función simple curry(f, x) que proporcionará el primer argumento a una función, y esperamos argumentos adicionales más adelante. La definición es bastante sencilla:

curry(f, x) = (xs...) -> f(x, xs...)

Una vez más, usamos la sintaxis de la función anónima , esta vez en combinación con la sintaxis del argumento variadic.

Podemos implementar algunas funciones básicas en estilo tácito (o sin puntos) usando esta función de curry .

julia> const double = curry(*, 2)
(::#19) (generic function with 1 method)

julia> double(10)
20

julia> const simon_says = curry(println, "Simon: ")
(::#19) (generic function with 1 method)

julia> simon_says("How are you?")
Simon: How are you?

Las funciones mantienen el generismo esperado:

julia> simon_says("I have ", 3, " arguments.")
Simon: I have 3 arguments.

julia> double([1, 2, 3])
3-element Array{Int64,1}:
 2
 4
 6

Introducción a los cierres

Las funciones son una parte importante de la programación de Julia. Se pueden definir directamente dentro de los módulos, en cuyo caso las funciones se denominan de nivel superior . Pero las funciones también se pueden definir dentro de otras funciones. Tales funciones se llaman " cierres ".

Los cierres capturan las variables en su función exterior. Una función de nivel superior solo puede usar variables globales de su módulo, parámetros de función o variables locales:

x = 0  # global
function toplevel(y)
    println("x = ", x, " is a global variable")
    println("y = ", y, " is a parameter")
    z = 2
    println("z = ", z, " is a local variable")
end

Un cierre, por otro lado, puede usar todos aquellos además de las variables de las funciones externas que captura:

x = 0  # global
function toplevel(y)
    println("x = ", x, " is a global variable")
    println("y = ", y, " is a parameter")
    z = 2
    println("z = ", z, " is a local variable")

    function closure(v)
        println("v = ", v, " is a parameter")
        w = 3
        println("w = ", w, " is a local variable")
        println("x = ", x, " is a global variable")
        println("y = ", y, " is a closed variable (a parameter of the outer function)")
        println("z = ", z, " is a closed variable (a local of the outer function)")
    end
end

Si ejecutamos c = toplevel(10) , vemos que el resultado es

julia> c = toplevel(10)
x = 0 is a global variable
y = 10 is a parameter
z = 2 is a local variable
(::closure) (generic function with 1 method)

Tenga en cuenta que la expresión de cola de esta función es una función en sí misma; Es decir, un cierre. Podemos llamar al cierre c como si fuera cualquier otra función:

julia> c(11)
v = 11 is a parameter
w = 3 is a local variable
x = 0 is a global variable
y = 10 is a closed variable (a parameter of the outer function)
z = 2 is a closed variable (a local of the outer function)

Tenga en cuenta que c todavía tiene acceso a las variables y y z desde la llamada de nivel toplevel , ¡aunque el nivel toplevel ya ha regresado! Cada cierre, incluso los devueltos por la misma función, se cierra sobre diferentes variables. Podemos llamar al nivel toplevel nuevo.

julia> d = toplevel(20)
x = 0 is a global variable
y = 20 is a parameter
z = 2 is a local variable
(::closure) (generic function with 1 method)

julia> d(22)
v = 22 is a parameter
w = 3 is a local variable
x = 0 is a global variable
y = 20 is a closed variable (a parameter of the outer function)
z = 2 is a closed variable (a local of the outer function)

julia> c(22)
v = 22 is a parameter
w = 3 is a local variable
x = 0 is a global variable
y = 10 is a closed variable (a parameter of the outer function)
z = 2 is a closed variable (a local of the outer function)

Tenga en cuenta que a pesar de que d y c tienen el mismo código y de haber pasado los mismos argumentos, su salida es diferente. Son distintos cierres.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow