Funciones y Closures
Definiciones de funciones, closures y recursión.
Las funciones son valores de primera clase en Achronyme. Pueden asignarse a variables, pasarse como argumentos y devolverse desde otras funciones.
Declaraciones de 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")
Funciones Anónimas
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)
Valores de Retorno
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.
Closures
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)
Funciones de Orden Superior
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)
Recursión
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)
Anotaciones de Tipo
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.
Referencia Rápida
| Característica | Sintaxis | Notas |
|---|---|---|
| Función con nombre | fn name(a, b) { body } | Elevada en el ámbito |
| Función anónima | fn(a, b) { body } | Valor de primera clase |
| Expresión de función con nombre | let f = fn f(n) { ... } | Permite recursión vía variable |
| Parámetros tipados | fn f(x: Field, y: Bool) | Opcional, verificado en circuitos |
| Tipo de retorno | fn f(x) -> Field { body } | Opcional, verificado en circuitos |
| Retorno implícito | última expresión del cuerpo | Sin necesidad de return |
| Retorno explícito | return expr | Salida anticipada |
| Captura de closure | automática | Por referencia |