Segredos

Segredos

Exercício de aprendizagem

Introdução

Funções anónimas

As funções são tratadas como cidadãos de primeira classe em Elixir. Isto significa que:

  • Funções nomeadas e anónimas podem ser atribuídas a variáveis.
  • Funções nomeadas e anónimas podem ser passadas como dados, como argumentos e valores devolvidos.
  • Funções anónimas podem ser criadas dinamicamente.

As funções anónimas, ao contrário das funções nomeadas, não têm uma referência estática disponível. Só estão disponíveis se forem atribuídas a uma variável ou invocadas imediatamente.

Podemos usar funções anónimas para:

  • Esconder dados usando âmbito lexical (também conhecido como closure).
  • Criar funções dinamicamente em tempo de execução.

As funções anónimas começam com a palavra reservada fn, os argumentos são separados do corpo da função com o token ->, e terminam com um end. Tal como nas funções nomeadas, a última expressão da função é devolvida implicitamente à função que a chama.

Para invocar uma referência de função, tens de usar um . entre a variável de referência e a lista de argumentos:

function_variable = fn param ->
  param + 1
end

function_variable.(1)
# => 2

Podes até usar notação de captura abreviada para tornar isto mais conciso:

variable = &(&1 + 1)

variable.(1)
# => 2

Manipulação de bits

O Elixir suporta muitas funções para trabalhar com bits no módulo Bitwise.

  • band/2: AND bit a bit
  • bsl/2: deslocamento para a esquerda bit a bit
  • bsr/2: deslocamento para a direita bit a bit
  • bxor/2: XOR bit a bit
  • bor/2: OR bit a bit
  • bnot/1: NOT bit a bit

Aqui está um exemplo de como usar uma função bit a bit:

Bitwise.bsl(1, 3)
# => 8

Todas as funções bit a bit só funcionam com números inteiros.

Se estiveres a usar a versão 1.9 do Elixir ou inferior, precisas de chamar require Bitwise no início da definição do módulo para poderes usar o módulo Bitwise.

Instruções

Neste exercício, a tua tarefa é escrever o software de um dispositivo de encriptação que funciona realizando transformações sobre os dados. Precisas de uma forma flexível de criar funções complicadas combinando funções mais simples.

Para cada tarefa, devolve uma função anónima que possa ser invocada a partir do âmbito de chamada.

Todas as funções devem esperar argumentos inteiros. Os números inteiros também são adequados para realizar operações bit a bit em Elixir.

1. Cria um somador

Implementa Secrets.secret_add/1. Deve devolver uma função que recebe um argumento e lhe soma o argumento passado a secret_add.

adder = Secrets.secret_add(3)
adder.(2)
# => 5

2. Cria um subtrator

Implementa Secrets.secret_subtract/1. Deve devolver uma função que recebe um argumento e subtrai a esse argumento o segredo passado a secret_subtract.

subtractor = Secrets.secret_subtract(2)
subtractor.(3)
# => 1

3. Cria um multiplicador

Implementa Secrets.secret_multiply/1. Deve devolver uma função que recebe um argumento e o multiplica pelo segredo passado a secret_multiply.

multiplier = Secrets.secret_multiply(7)
multiplier.(3)
# => 21

4. Cria um divisor

Implementa Secrets.secret_divide/1. Deve devolver uma função que recebe um argumento e o divide pelo segredo passado a secret_divide.

divider = Secrets.secret_divide(3)
divider.(32)
# => 10

Recorre à divisão inteira para que o resultado seja compatível com os valores de entrada esperados pelas outras funções.

5. Cria um "and"-er

Implementa Secrets.secret_and/1. Deve devolver uma função que recebe um argumento e realiza uma operação and bit a bit sobre esse argumento e o segredo passado a secret_and.

ander = Secrets.secret_and(1)
ander.(2)
# => 0

6. Cria um "xor"-er

Implementa Secrets.secret_xor/1. Deve devolver uma função que recebe um argumento e realiza uma operação xor bit a bit sobre esse argumento e o segredo passado a secret_xor.

xorer = Secrets.secret_xor(1)
xorer.(3)
# => 2

7. Cria um combinador de funções

Implementa Secrets.secret_combine/2. Deve devolver uma função que recebe um argumento e lhe aplica, pela ordem indicada, as duas funções passadas a secret_combine.

add_one = Secrets.secret_add(1)
multiply_by_2 = Secrets.secret_multiply(2)
combined = Secrets.secret_combine(add_one, multiply_by_2)

combined.(3)
# => 8
Editar via GitHub A ligação abre numa nova janela ou separador
Elixir Exercism

Estás pronto para começar Segredos?

Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.