func double(n: Int): Int { return n * 2 }
proc main(): void {
f := double
echo "{f(21)} {map([1, 2, 3], double)}"
}type Msg {
Changed { text: Str }
}
func add(a: Int, b: Int): Int { return a + b }
proc main(): void {
mut n := 5
addN := add(n, _) // _ vira o parâmetro; n é tomado agora
n = 100
echo addN(10) // 15 — o que foi fornecido ficou como estava
make := Msg.Changed(_) // uma função que constrói a variante
echo make("digitado")
}func double(n: Int): Int { return n * 2 }
func shout(s: Str): Str { return s + "!" }
func applyTwice(f: func(Int): Int, n: Int): Int { // como parâmetro
return f(f(n))
}
func picked(loud: Bool): func(Str): Str { // como retorno
return shout
}
proc main(): void {
func(Int): Int step = double // como tipo de variável
echo applyTwice(step, 5)
echo picked(true)("hive")
}proc grow(names: mut Str[dyn], name: Str): void {
append(names, name)
}
proc twice(step: proc(mut Str[dyn]): void, names: mut Str[dyn]): void {
step(names)
step(names)
}
proc main(): void {
mut Str[dyn] names = ["ada"]
twice(grow(_, "bee"), names) // o mutex continua um buraco
echo names
}proc third(v: Str[3]): void { echo v[2] }
proc anyLength(v: Str[]): void { echo len(v) }
proc callWithThree(f: proc(Str[3]): void): void {
f(["a", "b", "c"])
}
proc main(): void {
callWithThree(third) // vale: o espaço promete três
callWithThree(anyLength) // vale: qualquer tamanho aceita três também
// proc(Str[]): void g = third // erro de compilação: g pode ser chamado com um
}Algo chamável é um valor, feito de três jeitos:
f := double;_: add(5, _) é uma função de um argumento, cada buraco virando um parâmetro na ordem escrita. O que é fornecido é calculado uma vez, onde está escrito, e guardado: mudar a variável depois não muda nada do que a função guarda;Msg.Changed(_) é uma função que constrói a variante. Msg.Changed sozinho não é um valor.Seu tipo se escreve como uma declaração sem os nomes — func(Int): Int, proc(mut Str[dyn], Str): void — e serve como parâmetro, tipo de retorno e tipo de uma variável. Um valor func preenche um espaço de proc, nunca o contrário, e uma chamada por qualquer valor de função é conferida contra o tipo dele: quantos argumentos e o que cada um é, por posição, já que os parâmetros de um valor não têm nomes. Uma posição mut em uma aplicação parcial continua sendo um buraco, porque o que é fornecido é guardado como uma cópia que as escritas nunca alcançariam.
Um valor de função só preenche um espaço quando aceita tudo o que as chamadas daquele espaço podem lhe passar: um proc(Str[3]): void não pode ir onde se quer um proc(Str[]): void, já que esse espaço pode ser chamado com qualquer tamanho, enquanto o contrário vale. Uma função nativa, uma chamada da biblioteca e um chamável genérico não podem virar valores de jeito nenhum — embrulhe um deles em um func seu.