Trilhas
/
Julia
Julia
/
Exercícios
/
Namorada do ensino médio
Namorada do ensino médio

Namorada do ensino médio

Exercício de aprendizagem

Introdução

Julia incentiva quem programa a colocar o máximo de código possível dentro de funções que podem ser compiladas JIT, e criar muitas funções pequenas é, por design, performático.

Isso tende a deixar muitas funções pequenas e simples, que precisam ser combinadas para realizar tarefas não triviais.

Uma abordagem óbvia é aninhar chamadas de função. O exemplo a seguir é bem forçado, mas ilustra o ponto.

julia> first.(titlecase.(reverse.(["my", "test", "strings"])))
3-element Vector{Char}:
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)

A desvantagem dessa abordagem é que a legibilidade cai rapidamente conforme o aninhamento fica mais profundo.

Precisamos de uma abordagem mais simples e mais flexível.

Composição

Essa é a técnica querida dos matemáticos, e Julia copia a sintaxe matemática.

Um número arbitrário de funções pode ser composed com operadores ∘ (digitados como \circ e depois tab). O resultado pode ser usado como uma única função.

julia> compfunc = first ∘ titlecase ∘ reverse
first ∘ titlecase ∘ reverse
julia> compfunc.(["my", "test", "strings"])
3-element Vector{Char}:
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
# alternative syntax, giving the same result
julia> (first ∘ titlecase ∘ reverse).(["my", "test", "strings"])

Alguns pontos para observar:

  • As funções iniciais aparecem na mesma ordem de quando aninhadas, e são executadas da direita para a esquerda.
  • O broadcasting não é simples de usar ao compor, mas pode ser aplicado ao chamar a função composta.

Pipeline

Uma alternativa pode ser encarada como a abordagem dos programadores, em vez da dos matemáticos.

Pipelines são usados há muito tempo em scripts de shell do Unix, e mais recentemente se popularizaram nas linguagens de programação mainstream (às vezes se credita ao F# o pioneirismo na adoção deles).

O conceito básico é começar com alguns dados e então encaminhá-los por uma sequência de funções para obter o resultado.

O operador de pipe é |> (como em F# e nas versões recentes do R), embora Julia também tenha uma versão de broadcast .|>.

julia> ["my", "test", "strings"] .|> reverse .|> titlecase .|> first
3-element Vector{Char}:
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)

A execução agora é estritamente da esquerda para a direita, com a saída de cada função fluindo na direção da seta para se tornar a entrada da próxima função.

Limitações, soluções alternativas e outras opções

Não é coincidência que as funções usadas para ilustrar composição e pipelines recebam todas um único argumento.

Algumas linguagens puramente funcionais canalizam o primeiro argumento para uma função, mas permitem que outros sejam incluídos.

Em contraste, Julia espera apenas os nomes das funções (ou algo equivalente) em um pipeline, sem nenhum argumento adicional.

Há razões técnicas importantes para isso (relacionadas ao fato de que currying não é parte padrão do design da linguagem). As muitas pessoas que não entendem nada de currying devem apenas aceitar que essa limitação não é um descuido, e não deve mudar em versões futuras de Julia.

Soluções alternativas

Precisamos de funções de um único argumento que façam o que for preciso. Felizmente, definir novas funções em Julia é fácil.

Da forma mais simples, poderíamos usar uma anonymous function. Por exemplo, se temos uma única string de entrada e queremos dividir nos underscores:

julia> "my_test_strings" |> (s -> split(s, '_'))
3-element Vector{SubString{String}}:
 "my"
 "test"
 "strings"

Esse vetor poderia então ser encaminhado para outras funções, como antes.

Colocar a função anônima entre parênteses é opcional neste caso, mas, de forma mais geral, é uma maneira útil de reduzir ambiguidade.

Da mesma forma, poderíamos criar uma função nomeada, antes no programa, e reutilizá-la conforme necessário.

Instruções

Neste exercício, você vai ajudar namorados do ensino médio a declarar seu amor nas redes sociais, gerando um coração unicode com as iniciais deles:

❤ J.  +  M. ❤

1. Limpe o nome

Implemente o método cleanupname. Ele deve receber um nome, remover todos os caracteres - e substituí-los por um espaço. Ele também deve remover qualquer espaço em branco do início e do fim do nome.

julia> cleanupname("Jane-Ann")
"Jane Ann"

2. Obtenha a primeira letra do nome

Implemente o método firstletter. Ele deve receber um nome e retornar sua primeira letra como uma string. Certifique-se de reutilizar cleanupname, que você definiu na etapa anterior, e combiná-lo com outras funções.

julia> firstletter("Jane")
"J"

3. Formate a primeira letra como uma inicial

Implemente o método initial. Ele deve receber um nome e retornar sua primeira letra, em maiúscula, seguida de um ponto. Certifique-se de reutilizar firstletter, que você definiu na etapa anterior.

initial("Robert")
"R."

4. Coloque as iniciais dentro do coração

Implemente o método couple. Ele deve receber dois nomes e retornar as iniciais com corações emoji ao redor. Certifique-se de reutilizar initial, que você definiu na etapa anterior.

couple("Blake Miller", "Riley Lewis")
"❤ B.  +  R. ❤"
Editar via GitHub O link abre em uma nova janela ou aba
Julia Exercism

Tudo pronto para começar Namorada do ensino médio?

Crie sua conta no Exercism para aprender e dominar Julia com 35 conceitos128 exercícios e mentoria humana de verdade, tudo de graça.