Ações
Funções em DataForge: parâmetros, tipos, aridade, closures, lambdas, decoradores e defer.
Declarar#
action somar(a, b):
yield a + b
out somar(2, 3) # 5yield devolve o valor e encerra a ação. Sem yield, a ação devolve void.
Parâmetros#
Valores padrão#
action criar(nome, papel := "leitor", ativo := yes):
yield {"nome": nome, "papel": papel, "ativo": ativo}
out criar("Ana") # papel = "leitor"
out criar("Bruno", "admin")Argumentos nomeados#
action retangulo(largura := 1, altura := 1):
yield largura * altura
out retangulo(altura := 5, largura := 3) # 15 — fora de ordemTipos#
action media(nums: Cluster) -> Float:
yield sum(nums) / len(nums)
out media([1, 2, 3]) # 2.0Parâmetros e retorno são verificados. A mensagem de erro nomeia exatamente o parâmetro:
parameter 'nums' of action 'media' declared as Cluster but got StringAridade verificada#
Chamar com argumentos a mais ou a menos dispara erro — e o analisador estático acha isso antes de executar:
action f(a, b):
yield a + b
# f(1) -> action 'f' is missing argument(s): b
# f(1, 2, 3) -> action 'f' takes 2 argument(s) but 3 were givenRecursão#
action fatorial(n):
given n smaller_eq 1:
yield 1
yield n * fatorial(n - 1)
out fatorial(6) # 720Recursão infinita vira StackOverflowError_ após 1000 quadros, com o nome da ação culpada na mensagem. Recursões legítimas de até ~900 níveis funcionam.
Ações de alta ordem e closures#
action fabrica_somador(n):
action somador(x):
yield x + n # 'n' vem do escopo de fora — isso é a closure
yield somador
soma10 := fabrica_somador(10)
out soma10(5) # 15
out fabrica_somador(3)(4) # 7 — chamada encadeadaLambdas#
Três grafias, todas equivalentes:
dobro := lambda x: x * 2
soma := lambda a, b => a + b
fixo := lambda: 42
out [1, 2, 3].map(lambda n: n * n) # [1, 4, 9]
out [1, 2, 3, 4].filter(lambda n: n % 2 is 0) # [2, 4]Decoradores#
mark @nome envolve uma ação com outra, sem alterar seu corpo:
action com_log(fn):
action envolvida(x):
out $" [log] chamada com {x}"
yield fn(x)
yield envolvida
mark @com_log
action triplo(x):
yield x * 3
out triplo(5) [log] chamada com 5
15defer#
Agenda um bloco para rodar quando a ação terminar — em qualquer caminho de saída, inclusive por erro:
action com_recurso():
abrir()
defer:
fechar() # roda aconteça o que acontecer
processar()
yield "pronto"Vários defer rodam em ordem inversa (LIFO), que é a ordem correta para desmontar recursos dependentes. Detalhes em Tratamento de erros.