Funções
Funções são declaradas com a keyword fn. São cidadãos de primeira classe — podem ser passadas como valores e retornadas por outras funções.
Declaração básica
Section titled “Declaração básica”fn soma(a: Int, b: Int) -> Int { return a + b}O tipo de retorno vem após ->. Quando a função não retorna nada útil, o tipo é Unit (ou omitido):
fn log(msg: String) { print(msg)}Corpo de expressão única
Section titled “Corpo de expressão única”Funções simples podem usar = como açúcar para return:
fn dobrar(x: Int) -> Int = x * 2fn saudacao(nome: String) -> String = "Olá, $(nome)!"Retorno
Section titled “Retorno”Soyuz não tem retorno implícito. O return é sempre obrigatório em blocos {}:
fn soma(a: Int, b: Int) -> Int { return a + b // obrigatório}
// A única exceção é o corpo de expressão com =fn soma(a: Int, b: Int) -> Int = a + b // = é açúcar para returnRetorno múltiplo com tupla
Section titled “Retorno múltiplo com tupla”fn dividirComResto(a: Int, b: Int) -> (Int, Int) { return (a / b, a % b)}
val (quociente, resto) = dividirComResto(17, 5)Parâmetros
Section titled “Parâmetros”Anotação de tipo
Section titled “Anotação de tipo”Parâmetros sempre precisam de tipo anotado:
fn area(largura: Float, altura: Float) -> Float { return largura * altura}Parâmetros Default
Section titled “Parâmetros Default”Parâmetros podem ter valores padrão, que são usados se o argumento for omitido na chamada:
fn registrar(nome: String, cargo: String = "Desenvolvedor") { print("Registrando $(nome) como $(cargo)")}
registrar("Vand") // cargo = "Desenvolvedor"registrar("Lucas", "Gerente") // cargo = "Gerente"self — métodos
Section titled “self — métodos”Métodos em class recebem self como primeiro parâmetro:
class Contador { var count: Int = 0
fn incrementar(self) { self.count = self.count + 1 }}Overloading e when guards
Section titled “Overloading e when guards”Soyuz permite definir múltiplas versões de uma mesma função usando a keyword when. O compilador escolherá a definição correta baseada no predicado:
fn fatorial(n: Int) when n == 0 = 1fn fatorial(n: Int) = n * fatorial(n - 1)Regras de despacho
Section titled “Regras de despacho”- Ordem de Avaliação: O compilador testa as definições com
whenna ordem em que foram declaradas. - Variante Catch-all: É obrigatório fornecer uma implementação final sem o
whenguard para garantir que a função sempre possa ser executada.
Funções de primeira classe
Section titled “Funções de primeira classe”Funções podem ser passadas como argumentos e retornadas:
// Passada como argumentofn aplicar(f: (Int) -> Int, x: Int) -> Int { return f(x)}
val resultado = aplicar(dobrar, 5) // 10
// Retornada por outra funçãofn multiplicador(fator: Int) -> (Int) -> Int { return fn(x: Int) => x * fator}
val triplicar = multiplicador(3)triplicar(4) // 12Funções anônimas (arrow functions)
Section titled “Funções anônimas (arrow functions)”A sintaxe é fn(params) => corpo:
val pares = [1, 2, 3, 4, 5].filter(fn(x: Int) => x % 2 == 0)Aplicação Parcial (Partial Application)
Section titled “Aplicação Parcial (Partial Application)”Você pode criar uma nova função fixando alguns argumentos de uma função existente usando o caractere _:
fn multiplicar(x: Int, y: Int) -> Int = x * y
val dobrar = multiplicar(2, _) // (Int) -> Intval triplicar = multiplicar(3, _) // (Int) -> Int
dobrar(10) // 20triplicar(10) // 30Genéricos em funções
Section titled “Genéricos em funções”fn identidade[T](x: T) -> T { return x}
fn primeiro[T](lista: List[T]) -> Option[T] { return lista.first()}Com constraints
Section titled “Com constraints”fn maior[T : Comparable](a: T, b: T) -> T { if a > b { return a } return b}Visibilidade
Section titled “Visibilidade”Por padrão, funções são privadas ao módulo. Use pub para exportar:
pub fn exportada(x: Int) -> Int = x * 2 // visível para outros módulosfn interna(x: Int) -> Int = x + 1 // só neste arquivo