andrews medina

DSLs em Python

escrito em 11/12/2010

introdução

DSL (Domain Specifc Language) é uma linguagem limitada com o objetivo de atender um domínio específico. Ou seja, DSLs são uma forma diferente de programar, onde é criado uma sintaxe que se aproxime mais do domínio do qual ela faz parte.

A linguagem de programação escolhida para construir a DSL afeta totalmente em como será a sintaxe da DSL. Geralmente, linguagens menos burocráticas como ruby são mais utilizadas para construção de DSLs.

Python mesmo sendo dinâmica tem várias burocracias, como endentação obrigatória, monkey patch limitado, que limitam a construção de DSLs, mas por outro lado, Python, tem características que podem ser utilizadas, como: sobrecarga de operadores, decorators e modificação do encoding.

Nesse post eu mostrarei como utilizar essas técnicas para construção de DSLs, e mostrar bibliotecas em Python que já as utilizam.

sobrecarga de operadores

Há duas formas de utilizar a sobrecarga de operadores para construir DSLs. Uma delas é mantendo a função original do operador, mas modificando o domínio em que ele atua, e a outra forma é modificando a função do operador, utilizando ele apenas para facilitar a sintaxe.

Para exemplificar como podemos utilizar um operador, mantendo sua função original, mas modificando seu domínio, vamos analizar o funcionamento o operador de adição (+):

Ele pode ser utilizado para realizar a adição, somando dois números:


>>> 2 + 2
4

Pode ser utilizado para concatenar duas strings:


>>> “andrews” + “medina”
“andrews medina”

Seguindo esse raciocínio poderíamos usar o operador de adição para concatenar duas imagens:


>>> imagem1 + imagem2

Um framework que faz um ótimo uso de sobrecarga de operadores, mantendo sua função é o cocos2d. Ele utiliza operadores para concatenar ações/animações:


>> sprite.do( Reverse(scale) + scale )

A outra forma, de usar operadores é apenas sobrescrevendo ele para usar ele de uma forma que fique ‘visualmente’ agradável, criando assim uma DSL.

Um exemplo de biblioteca que utiliza essa técnica é a should_dsl:


>> 1 |should| equal_to(1)

decorators

Usar decorators para descrever características de uma função, é uma técnica para escrever DSLs, tornando o código mais claro e legível.

Um exemplo, seria construir um decorator para tornar funções assíncronas:


@assync
def funcao():
pass

O uso de decorators é bem comum. Outro caso é utilizar decorators para definir o roteamento de ur utilizado por uma função:


@url(‘foo’)
def foo():
pass

O django utiliza decorators para facilitar a construção de filtros e template tags:


@filter
def hello():
return “hello”

Além do django, o lettuce, web2py, flask utilizam decorators.

modificação do encoding

Uma outra forma mais livre de construir DSLs em Python é utilizando o encoding para modificar a sintaxe do Python.

Essa técnica não é muito comum e eu particularmente não gosto dela, por ela modificar a sintaxe original da linguagem.

Um exemplo de uso dela pode ser visto num projeto criado pelo Fernando Meyer, chamado YETI (https://github.com/fmeyer/yeti):


describe Bowling:
def before_each:
self._bowling = Bowling()

it "should score 0 for gutter game":
self._bowling.hit(0)
self._bowling.score |should_be.equal_to| 0

Para quem quiser entender mais como funciona o YETI, Meyer escreveu um post sobre isso: http://planeta-globo.com/2009/09/05/writing-a-domain-specific-language-dsl-with-python/

conclusão

Para saber quando usar sobrecarga de operadores, decorators ou criar uma sintaxe diferente na hora de criar uma DSL, lembre-se sempre de torná-la mais simples possível e sempre condizente ao domínio.

blog comments powered by Disqus