Páginas

Friday, May 27, 2011

Boo não é Python

Ontem no Coding Dojo Rio no Centro do Rio de Janeiro tivemos uma nova linguagem para experimentar. Em linhas gerais o dojo foi sensacional, e não só os minutos que estávamos lá programando mas também as discussões que rolaram até tarde. Cheguei a casa já eram 2:40!

O problema que abordamos foi o do Caixa Eletrônico. Graças ao Juan Lopes nós usamos Boo e um super dojo timer novinho em folha. A idéia deste post é apenas discutir brevemente um aspecto da linguagem que me chamou a atenção.

Portanto, que fique claro que, apesar da maior parte da sintaxe ser parecida, as linguagens não são as mesmas, e algumas escolhas semânticas e gramaticais deixam isto claro. Também não se trata do que é melhor e o que é pior.

Ontem fiquei curioso pois numa parte obscura do nosso código tínhamos uma função mais ou menos assim:

def sacar(valor):
    return (valor,) if valor in (2, 5, 10, 20, 50, 100)
    
    raise EntradaInconsistente() if valor <= 0
    
    return (20, 20) if valor == 40
    
    return (2,) + sacar(valor - 2) if (valor - 2) in (2, 5, 10, 20, 50, 100)

Possívelmente não era exatamente isto, mas era algo muito parecido e equivalente. Tínhamos 4 linhas que eram raise ou return, seguido de um valor de retorno, seguido de um if e uma condição.

Não demorou para percebermos que a legibilidade estava ruim, pois para saber o que cada linha fazia era preciso ler a linha inteira. Se os if's estiverem em suas próprias linhas, fica mais fácil ler a condição e "ignorar" o bloco de código (mesmo que uma expressão curta...) que se segue.

    if valor in (2, 5, 10, 20, 50, 100):
        return (valor,)

Mas isto pode ser considerada apenas uma questão estilistica...

O ponto é que eu jurava que "return (20, 20) if valor == 40" não é uma linha válida de Python! Sim, de Python... mas estávamos programando em Boo.

Acabou que nós não testamos lá, e ficou o suspense. Em Ruby reza a lenda que isto funciona e é super normal, mas em Python... em Python a história é outra.
Eu fui testar agora no ipython:

In [1]: def foo(x, y):
   ...:     return "x par" if x%2==0
------------------------------------------------------------
   File "", line 2
     return "x par" if x%2==0
                             ^
SyntaxError: invalid syntax


In [3]: def foo(x, y):
    return "x par" if (x%2==0)
------------------------------------------------------------
   File "", line 2
     return "x par" if (x%2==0)
                               ^
SyntaxError: invalid syntax


In [5]: def foo(x, y):
    return "x par" if (x%2==0) else 0
   ...:

E foram confirmadas minhas expectativas de que isso não funciona em Python :D

Tanto return quanto raise são palavras-chave que formam gramaticalmente uma declaração (statement) em Python. E a declaração é "return truthy_value if condition else falsy_value", como pode ser visto na gramática.

A semântica quando se começa uma linha por return é que a função vai retornar o que quer que seja o valor avaliado para o que vem depois da palavra-chave (a não ser claro que antes disso ocorrer uma exceção seja lançada).

E é só isso...

Nota: não encontrei a gramática do Boo para linkar...
Nota mental: espero fazer mais desses posts ao invés de mandar emails longos :D


[update 26/05/2011 20:08]
O Juan acrescentou na lista do Dojo sobre a gramática de Ruby:

STMT : STMT if EXPR
STMT : EXPR
EXPR : ARG
ARG : PRIMARY
PRIMARY : return [`(' [CALL_ARGS] `)']

E então, comparando com Python (já que eu tinha só linkado antes):

return_stmt: 'return' [testlist]
testlist: test (',' test)* [',']
test: or_test ['if' or_test 'else' test] | lambdef

Agora só fica faltando formalizar a gramática do Boo. Fiz uma busca de novo no Google e no site oficial do Boo, mas não achei! Será que você tem mais sorte?

1 comment:

Jonatas Emidio said...

Salve Rodolfo!!

Show de Post...
Eu realmente tinha uma ideia errada sobre o Boo!!