Ir al contenido

Funciones y Closures

Las funciones son valores de primera clase en Achronyme. Pueden asignarse a variables, pasarse como argumentos y devolverse desde otras funciones.

Define funciones con nombre usando fn name(params) { body }.

fn add(a, b) {
return a + b
}
assert(add(3, 4) == 7)
fn greet() {
return "hello"
}
assert(greet() == "hello")

Crea funciones sin nombre con fn(params) { body } y asígnalas a variables.

let double = fn(x) { x * 2 }
assert(double(5) == 10)
let mul = fn(a, b) { return a * b }
assert(mul(3, 7) == 21)

La última expresión en el cuerpo de una función es su valor de retorno. Usa return para salidas anticipadas.

fn square(x) {
x * x
}
assert(square(4) == 16)
fn abs(x) {
if x >= 0 { return x }
return -x
}
assert(abs(-5) == 5)

Las funciones sin return y sin expresión final devuelven nil.

Las funciones capturan variables de su ámbito circundante por referencia. Los cambios en variables capturadas son visibles para todos los closures que las comparten.

fn make_adder(n) {
return fn(x) { x + n }
}
let add5 = make_adder(5)
assert(add5(3) == 8)

Los closures pueden capturar y mutar estado:

fn make_counter() {
mut count = 0
return fn() {
count = count + 1
return count
}
}
let counter = make_counter()
assert(counter() == 1)
assert(counter() == 2)
assert(counter() == 3)

Múltiples closures pueden compartir la misma variable mutable:

fn make_pair() {
mut val = 0
let getter = fn() { val }
let setter = fn(x) { val = x }
return [getter, setter]
}
let pair = make_pair()
let get = pair[0]
let set = pair[1]
assert(get() == 0)
set(42)
assert(get() == 42)

Las funciones pueden aceptar y devolver otras funciones.

fn apply(f, x) {
return f(x)
}
assert(apply(fn(x) { x * x }, 5) == 25)
fn compose(f, g) {
return fn(x) { f(g(x)) }
}
let inc = fn(x) { x + 1 }
let dbl = fn(x) { x * 2 }
let inc_then_dbl = compose(dbl, inc)
assert(inc_then_dbl(3) == 8)

Patrones comunes como map, filter y reduce:

fn filter(arr, pred) {
mut result = []
for x in arr {
if pred(x) { push(result, x) }
}
return result
}
let evens = filter([1, 2, 3, 4, 5, 6], fn(x) { x % 2 == 0 })
assert(len(evens) == 3)
fn reduce(arr, init, f) {
mut acc = init
for x in arr { acc = f(acc, x) }
return acc
}
assert(reduce([1, 2, 3, 4, 5], 0, fn(a, b) { a + b }) == 15)

Las funciones con nombre pueden llamarse a sí mismas. Usa expresiones de función con nombre (fn name(params) { ... }) cuando asignes una función recursiva a una variable.

fn factorial(n) {
if n <= 1 { return 1 }
return n * factorial(n - 1)
}
assert(factorial(5) == 120)
let fib = fn fib(n) {
if n < 2 { return n }
return fib(n - 1) + fib(n - 2)
}
assert(fib(10) == 55)

Las funciones pueden incluir anotaciones de tipo opcionales en parámetros y tipos de retorno:

fn add(a: Field, b: Field) -> Field {
return a + b
}
fn is_positive(x: Field) -> Bool {
return x > 0
}
let double = fn(x: Field) -> Field { x * 2 }

Se permite mezclar parámetros tipados y no tipados — esto es tipado gradual:

fn scale(x: Field, factor) {
x * factor
}

En modo circuito, las anotaciones se verifican en tiempo de compilación. Consulta Anotaciones de Tipo para detalles sobre reglas de verificación de tipos y ahorro de restricciones.

CaracterísticaSintaxisNotas
Función con nombrefn name(a, b) { body }Elevada en el ámbito
Función anónimafn(a, b) { body }Valor de primera clase
Expresión de función con nombrelet f = fn f(n) { ... }Permite recursión vía variable
Parámetros tipadosfn f(x: Field, y: Bool)Opcional, verificado en circuitos
Tipo de retornofn f(x) -> Field { body }Opcional, verificado en circuitos
Retorno implícitoúltima expresión del cuerpoSin necesidad de return
Retorno explícitoreturn exprSalida anticipada
Captura de closureautomáticaPor referencia