Segredos

Segredos

Exercício de aprendizagem

Introdução

Funções anônimas

As funções são tratadas como cidadãs de primeira classe no Elixir. Isso 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, tanto como argumentos quanto como valores de retorno.
  • Funções anônimas podem ser criadas dinamicamente.

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

Podemos usar funções anônimas para:

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

Funções anônimas começam com a palavra reservada fn, os argumentos são separados do corpo da função pelo token ->, e são finalizadas com um end. Assim como nas funções nomeadas, a última expressão da função é retornada implicitamente para a função que a chamou.

Para invocar uma referência de função, você deve 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

Você pode até usar a notação de captura abreviada para deixar isso mais conciso:

variable = &(&1 + 1)

variable.(1)
# => 2

Manipulação de bits

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

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

Veja 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 você estiver rodando o Elixir na versão 1.9 ou inferior, vai precisar chamar require Bitwise no início da definição do módulo para conseguir usar o módulo Bitwise.

Instruções

Neste exercício, você tem a tarefa de escrever o software de um dispositivo de criptografia que funciona realizando transformações nos dados. Você precisa de uma forma de criar funções complicadas de maneira flexível, combinando funções mais simples.

Para cada tarefa, retorne uma função anônima que possa ser invocada a partir do escopo que a chama.

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

1. Crie um somador

Implemente Secrets.secret_add/1. Ela deve retornar uma função que recebe um argumento e soma a ele o argumento passado para secret_add.

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

2. Crie um subtrator

Implemente Secrets.secret_subtract/1. Ela deve retornar uma função que recebe um argumento e subtrai desse argumento o segredo passado para secret_subtract.

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

3. Crie um multiplicador

Implemente Secrets.secret_multiply/1. Ela deve retornar uma função que recebe um argumento e o multiplica pelo segredo passado para secret_multiply.

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

4. Crie um divisor

Implemente Secrets.secret_divide/1. Ela deve retornar uma função que recebe um argumento e o divide pelo segredo passado para secret_divide.

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

Use a divisão inteira para que a saída seja compatível com a entrada esperada pelas outras funções.

5. Crie um operador "and"

Implemente Secrets.secret_and/1. Ela deve retornar uma função que recebe um argumento e realiza uma operação and bit a bit entre ele e o segredo passado para secret_and.

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

6. Crie um operador "xor"

Implemente Secrets.secret_xor/1. Ela deve retornar uma função que recebe um argumento e realiza uma operação xor bit a bit entre ele e o segredo passado para secret_xor.

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

7. Crie um combinador de funções

Implemente Secrets.secret_combine/2. Ela deve retornar uma função que recebe um argumento e aplica a ele, na ordem, as duas funções passadas para 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 O link abre em uma nova janela ou aba
Elixir Exercism

Tudo pronto para começar Segredos?

Crie sua conta no Exercism para aprender e dominar Elixir com 58 conceitos168 exercícios e mentoria humana de verdade, tudo de graça.