DEV Community

Elixir UTFPR (por Adolfo Neto)
Elixir UTFPR (por Adolfo Neto)

Posted on

Um errinho em Elixir

Elixir não é uma linguagem perfeita, claro.

O "erro" que vou comentar aqui está na função Enum.at/3.

Deixa explicar melhor. Se eu tenho uma lista com 5 elementos:

[:a, :b, :c, :d, :e]
Enter fullscreen mode Exit fullscreen mode

e eu perguntar a você qual é o terceiro elemento, obviamente você vai me responder que é o :c.

Mas se eu usar Enum.at/3 da seguinte forma:

Enum.at([:a, :b, :c, :d, :e],3)
Enter fullscreen mode Exit fullscreen mode

o resultado vai ser:

iex> Enum.at([:a, :b, :c, :d, :e],3)
:d
Enter fullscreen mode Exit fullscreen mode

Interessante é que é um "erro" (coloco entre aspas por não ser um erro de verdade mas sim uma escolha que eu acredito ser errada) que não veio do Erlang:

> lists:nth(3, [a, b, c, d, e]).
c
Enter fullscreen mode Exit fullscreen mode

O Maxsuel Maccari explicou neste tweet a razão provável deste erro estar em Elixir. Ruby faz isso. Veja aqui e abaixo:

arr = [1, 2, 3, 4, 5, 6]
arr[2]    #=> 3
arr[100]  #=> nil
arr[-3]   #=> 4
Enter fullscreen mode Exit fullscreen mode

Ruby adiciona requintes de crueldade permitindo índices negativos.

Top comments (10)

Collapse
 
wldomiciano profile image
Wellington Domiciano •

Eu entendi que por erro vc quis dizer "decisão errada que não veio de Erlang", mas não dá para concluir isso comparando Enum.at com lists:nth, pois como já podemos ver pelos nomes, são completamente diferentes.

A descrição de Enum.at é:

Finds the element at the given index (zero-based).

"Encontra o elemento no índice fornecido".

Se eu escrevo Enum.at([:a, :b, :c, :d, :e],3) eu não estou dizendo "me dá o terceiro elemento", estou dizendo "me dá o elemento que está no índice 3", e já que índice começa no 0, é esperado que o resultado seja :d.

Já a descrição de lists:nth é:

Returns the Nth element of List.

"Retorna o enésimo elemento da lista".

Se eu escrevo lists:nth(3, [a, b, c, d, e]) estou dizendo que quero o terceiro elemento.


Ou seja, Enum.at faz exatamente o que o nome sugere e a documentação descreve.

Collapse
 
elixir_utfpr profile image
Elixir UTFPR (por Adolfo Neto) • • Edited

Eu chamaria apenas de "decisão errada". O fato de ter vindo de Erlang ou não pouco importa.

Erlang não tem um Enum, certo? O mais próximo de Enum, mas que é conceitualmente diferente, é lists.

Não faz diferença no que eu considero "erro" o fato da documentação da função Enum.at descrever exatamente o que ela faz. Não é um bug.

O "erro" (sempre entre aspas) se repete em Elixir no módulo List, nas funções delete_at, pop_at e provavelmente outras.

Nada que me impeça de amar Elixir.

Collapse
 
rhamorim profile image
Roberto Amorim •

Acesso a arrays baseado em zero não é erro - é um legado da forma como se indexa em C. É uma consequência da forma como "aritmética de ponteiros" funciona, e que é - pra quem trabalha com C e outras linguagens mais "perto do metal" - a maneira mais "natural" de pensar nesse tipo de indexação.

Em outras palavras: não é um erro, é uma escolha. Pode-se até argumentar que seja uma escolha ruim (ou que seja anacrônica ou contraproducente numa linguagem mais "abstrata"), mas é uma escolha que tem razão de existir e vários argumentos a favor (e contra).

Thread Thread
 
elixir_utfpr profile image
Elixir UTFPR (por Adolfo Neto) • • Edited
Collapse
 
wlsf profile image
Willian Frantz •

Curioso esse jeito de pensar, mas eu não vejo como um erro em nenhum ponto.

Desde o período de faculdade, sempre gostei de acreditar que lidar com indexes deveria ser assim mesmo, pois se parar pra pensar a gente considera o index 0 como sendo nosso ponto de partida, e a partir dele eu consigo pular pra qualquer index que eu quiser somente determinando quantas casas eu quero pular, e inclusive consigo ter noção da distância.

Ex:

arr = [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

Se eu parto do index 0 onde o valor é 1 arr[0] == 1, então eu consigo claramente saber que pra chegar no valor 3, eu preciso pular exatas 2 casas pra direita. arr[2] == 3

E também consigo determinar que o valor 3 está a exatas 2 casas de distância do valor 1 (que se encontra no index 0)

Collapse
 
elixir_utfpr profile image
Elixir UTFPR (por Adolfo Neto) •

Mas o ponto de partida dos seres humanos não devs é um. Se eu começo a contar laranjas, eu começo de 1. Qualquer explicação que não leve isto em consideração, está apenas justificando um "erro".

Collapse
 
wlsf profile image
Willian Frantz • • Edited

Mas "contar laranjas" me parece uma coisa bem diferente de posicionar essas laranjas em índices. Dispor elas de uma forma que você possa calcular a distância entre uma laranja até outra.

ex: Tendo em vista que você tem 4 laranjas, e você já está posicionado na primeira laranja, quantas laranjas você precisa pular pra conseguir alcançar a laranja numero 4? Seriam 3 pulos.

Você consegue contar elementos em Elixir normalmente sem precisar levar em consideração o índice em que estes elementos estão posicionados.

Enum.count(list)

Thread Thread
 
elixir_utfpr profile image
Elixir UTFPR (por Adolfo Neto) •
  1. Estou pensando em contar no sentido de 1, 2, 3,..., não de calcular o total de elementos de uma lista. Você está certo, claro. Eu que misturei.

  2. "Dispor elas de uma forma que você possa calcular a distância entre uma laranja até outra." Este é meu ponto: se eu tenho uma função que me dá um elemento de uma coleção ordenada, e eu quero o terceiro elemento, a função deveria receber 3 para me dar o terceiro elemento. Isto é o principal, não o cálculo de distâncias entre os elementos. Lembrando sempre que o meu ponto de vista é: o que vai facilitar para iniciantes?

Mas, como já disse em outros comentários, isto é um "errinho" mínimo. Elixir é quase perfeita.

Collapse
 
lucassperez profile image
Lucas Perez • • Edited

Sinceramente, índices negativos pra arrays são uma mão na roda. Se você quiser pegar o último elemento, pode fazer array[-1]. Inclusive isso nem é específico de Ruby.

Já em Elixir, os índices quase nem importam, uma vez que acessar um elemento por índice numa lista ligada é uma tarefa provavelmente pouco produtiva. Além disso, existem linguagens que indexam a partir do 1 e uma decisão assim normalmente gera discórdia e estranhamento 😅

Collapse
 
elixir_utfpr profile image
Elixir UTFPR (por Adolfo Neto) •

Sim, índice negativo deve ser uma ferramenta fantástica para programadores avançados.