Erlang: melhor que Python?

Vamos implementar a nossa função das aulas anteriores em Python?

Vamos!

#!/usr/bin/python
# -*- coding: utf-8 -*-

def interpretar_linhas(filename):
    with open(filename) as arquivo:
        for linha in arquivo:
            if not linha.startswith('#'):
                print linha,

if __name__ == '__main__':
    import sys
    interpretar_linhas(sys.argv[1])

Sim, eu sei que tem menos linhas e sei que o código aparenta ser mais claro. É quase desonesto comparar esse tipo de requisito (jogar na tela um arquivo texto com todas as linhas que não comecem com “#”) implementado em Python com qualquer outra linguagem.

(Mas, claro, um Perl monk conseguiria fazer isso tudo em uma linha só (eu acho).)

Seja como for, nossa comparação tem que ser mais abrangente. Mais do que, simplesmente, fazer o serviço, temos que analisar outros fatores no código. Por exemplo: pontos de entrada para novas funcionalidades. Vejamos nossa implementação em Erlang:

-module(funcoes).
-export([ler_arquivo/1]).

ler_arquivo(Filename) -ᐳ
    {Status, Fd} = file:open(Filename, [read]),
    ler_arquivo(Status, Fd).

ler_arquivo(error, Reason) -ᐳ
    io:format("Erro '~s' ao abrir o arquivo.", [erlang:atom_to_list(Reason)]);
ler_arquivo(ok, Fd) -ᐳ
    interpretar_linha(file:read_line(Fd), Fd).

interpretar_linha({ok, [$#|Resto]}, Fd) -ᐳ
    interpretar_linha(file:read_line(Fd), Fd);
interpretar_linha({ok, Linha}, Fd) -ᐳ
    io:format("~s", [Linha]),
    interpretar_linha(file:read_line(Fd), Fd);
interpretar_linha(eof, Fd) -ᐳ
    file:close(Fd).

Mais linhas, não? E parece mais confuso, eu sei.

Rodando um cloc (count lines of code), temos o seguinte: 8 linhas de código Python versus 16 linhas de código Erlang. Entretanto, o código em Erlang tem mais pontos de entrada para novas funcionalidades.

Por exemplo, um novo requisito no meu programa: ao encontrar uma linha que começa com ’#’, eu quero imprimir a linha sem o ’#’ do começo. Em Erlang, o ponto de entrada fica logo depois da linha 13. Em Python, eu teria que inserir um else após a linha 9. E, o pior de tudo: eu teria que meter minha mão (com meu “toque de Mirdas”) numa função que já está funcionando, possivelmente gerando um erro nela (quem vai saber o nível de sobriedade do programador, certo?). Em Python, essa função representa 90% da funcionalidade do código, ou seja: eu coloco em risco praticamente o programa todo. Já em Erlang, a função que eu lido representa uns 16% da funcionalidade, ou seja: eu mantenho 84% do código inalterado e, a princípio, seguro.

Além disso, nosso código Python não cobre a possibilidade de eu passar um caminho para um arquivo inexistente. Logo, para abranger as possibilidades de extensão e tratar o erro de abertura de arquivo, o código Python deveria ser assim:

#!/usr/bin/python
# -*- coding: utf-8 -*-

def interpretar_linhas(filename):
    try:
        with open(filename) as arquivo:
            for linha in arquivo:
                if not linha.startswith('#'):
                    print linha,
                else:
                    pass
    except IOError as e:
        print "Erro ao abrir o arquivo:", e
    except Exception as e:
        print "Erro:", e

if __name__ == '__main__':
    import sys
    interpretar_linhas(sys.argv[1])

Bom, já temos 15 linhas de código Python (no cloc). Quase a mesma coisa que nossa solução em Erlang, e com a diferença de, ao alterar a funcionalidade, expor 90% dela a riscos/erros/bugs, contra 16% de exposição em Erlang.

Então Erlang é melhor que Python?

Não!

Eu adoro programar em Python e não é o objetivo dessa aula dizer que uma linguagem é melhor que a outra (o título é só para instigar a curiosidade). De forma alguma. A ideia é desfazer preconceitos e mitos sobre legibilidade, manutenção e estensibilidade. Erlang é chamada, às vezes, de “linguagem arcaica”, o que eu não acredito ser verdade. A sintaxe pode ser estranha para quem está começando a aprender a linguagem, mas nada indica que seja “velha” ou “ultrapassada”.

Esquisitices de sintaxe por esquisitices, cada linguagem tem a sua. name do Python parece estranhíssimo para os iniciantes, assim como os… as… |coisasentrepipes| do Ruby ou os comentários com “–” (dois traços) de Lua. Cabe ao programador saber como lidar com cada uma.

Resumo


Este artigo foi originalmente escrito em 03/12/2014.