| « MySQL deixará de suportar o BerkeleyDB | Reinventando JavaScript em JavaScript » |
Questão de nomes
Trabalhar com mais de uma linguagem, geralmente é divertido. Você aprende diferentes formas de pensar no mesmo problema, e diferentes modos de resolvê-lo. Até que você aprende diferentes nomes pras mesmas coisas.
Partial
Um partial do python 2.5 não é a mesma coisa que o partial do rails. No python 2.5, o partial é uma forma de escrever funções que possam ter alguns parâmetros preenchidos de antemão, e chamadas sempre com esses parâmetros. Exemplo retirado de http://docs.python.org/dev/whatsnew/pep-309.html:
import functools
def log (message, subsystem):
"Write the contents of 'message' to the specified subsystem."
print '%s: %s' % (subsystem, message)
...
server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
São semelhantes às Curried functions , algo comum em Haskel, e implementável em outras linguagens. Oi dois nomes, aliás, vem do criador do Haskell, Haskell Curry.
Já um partial no rails, é um pequeno trecho do template, que é utilizado em mais de uma view. Exemplo retirado de http://api.rubyonrails.com/classes/ActionView/Partials.html :
<%= render :partial => "account" %>
Que iria renderizar a partial _account.rhtml com a variável @acount.
Ou então:
<%= render :partial => "account", :locals => { :account => @buyer } %>
<% for ad in @advertisements %>
<%= render :partial => "ad", :locals => { :ad => ad } %>
<% end %>
Que iria renderizar a partial account com a variável @buyer passada como a variável local no lugar de acount, e depois iria renderizar a partial ad e passar a variável @ad para a template.
Yield
Yield, em python, é usado nos generators. Generators são uma forma de gerar iterators.O yield faz com que a função pare onde ele for chamado, e que na próxima vez que for chamada, os valores sejam os mesmos da vez anterior. Um exemplo retirado da wikipedia:
def countfrom(n):
while True:
yield n
n += 1
# Exemplo: imprimir os inteiros de 10 a 20.
# Note que essa iteração termina normalmente, a despeito de countfrom() estar dentro de um loop infinito
for i in countfrom(10):
if i <= 20:
print i
else:
break
O yield é usado, por exemplo, ao ler um arquivo linha a linha:
f = open('links.txt')
for line in f:
print(line)
Em cada passo do loop for o iterador é avançado para a próxima linha. A vantagem nesse caso é podermos ler o arquivo preguiçosamente, linha a linha, sem armazená-lo inteiro em memória.
Uma dos usos do yield é implementar co-rotinas em python. (veja http://www.python.org/dev/peps/pep-0342/ ).
Em Lua, aliás, o yield é usado para resumir uma co-rotina.
Em Ruby, porém, o yield, é usado para uma função receber um bloco de código. Um trechozinho que peguei emprestado do livro do Taq.
def teste(n)
yield(n)
end
teste(2) { |i| i*i}
teste(3) { |i| i*i}
teste(4) { |i| i*i}
Porém, tem uma pegadinha aqui. Quando o bloco é executado, o controle volta pra linha imediatamente após o yield. Veja:
def itera()
a = 1
while a<10
yield a
a = a +1
end
end
itera(){|v| print(v, " ")}
Decorator
Decorator é o nome de um design pattern, definido pela famosa gangue dos quatro. Ele é definido como:
"Adicionar responsabilidades adicionais em um objeto dinamicamente. Decorators provêem uma alternativa flexível para a herança com meio de adicionar funcionalidade."
Para mais consulta a página da wikipedia sobre o Design Pattern Decorator .
O decorator é uma forma de adicionar funcionalidades à uma classe sem recorrer à herança, em tempo de execução.
Entre as novidades do python 2.4 estava o decorator (que segundo meu amigo Cacilhas é tanto um operador como um açucar sintático. Eu nunca tinha ouvido essa expressão antes de ler sobre a linguagem Lua, tanto que na época achei que era algo específico da linguagem. Uma das desvantagens de só saber a história tarde demais).
O exemplo da wikipedia é perfeitamente implementável em python, sem necessidade do operador @. Não é possível implementar o design pattern decorator ao pé da letra com python usando o decorator do python 2.4 - embora seja possível decorar funções e métodos.
Segue a implementação em python:
class SimpleWindow(object):
def draw(self):
print ('Desenhando janela simples')
def getDescription(self):
return('Janela simples')
class HorizontalDecorator(object):
def __init__(self,window):
self.__decoratedWindow = window
def drawHorizontalScrollbar(self):
print('Desenhando barra de rolagem horizontal')
def draw(self):
self.drawHorizontalScrollbar()
self.__decoratedWindow.draw()
def getDescription(self):
return self.__decoratedWindow.getDescription() + ', incluindo barra de rolagem horizontal'
class VerticalDecorator(object):
def __init__(self,window):
self.__decoratedWindow = window
def drawVerticalScrollbar(self):
print('Desenhando barra de rolagem vertical')
def draw(self):
self.drawVerticalScrollbar()
self.__decoratedWindow.draw()
def getDescription(self):
return self.__decoratedWindow.getDescription() + ', incluindo barra de rolagem horizontal'
janelaDecoradaTeste = HorizontalDecorator(VerticalDecorator(SimpleWindow()))
print(janelaDecoradaTeste.getDescription())
Que com poucas modificações, se torna a nossa versão em ruby:
class SimpleWindow
def draw()
print ('Desenhando janela simples')
end
def getDescription()
return('Janela simples')
end
end
class HorizontalDecorator
def initialize(window)
@decoratedWindow = window
end
def drawHorizontalScrollbar()
print('Desenhando barra de rolagem horizontal')
end
def draw()
drawHorizontalScrollbar()
@decoratedWindow.draw()
end
def getDescription()
return @decoratedWindow.getDescription() + ', incluindo barra de rolagem horizontal'
end
end
class VerticalDecorator
def initialize(window)
@decoratedWindow = window
end
def drawVerticalScrollbar()
print('Desenhando barra de rolagem vertical')
end
def draw()
drawVerticalScrollbar()
@decoratedWindow.draw()
end
def getDescription()
return @decoratedWindow.getDescription() + ', incluindo barra de rolagem horizontal'
end
end
janelaDecoradaTeste = HorizontalDecorator.new(VerticalDecorator.new(SimpleWindow.new))
puts(janelaDecoradaTeste.getDescription())
Ainda segundo uma dica do Cacilhas, a melhor forma de decorar uma classe em python seria com uma metaclasse.
Que venham os aspectos...
Andei dando uma lida sobre Programação Orientada a Aspectos (AOP), que é um assunto discutido atualmente na comunidade Java, e Design Patterns, tudo porque eu queria entender como funcionava o decorator do python, e estudar um pouco de design patterns.
Segundo o artigo disponível em: http://www-128.ibm.com/developerworks/java/library/j-aopwork5/ , em Java, o padrão decorator praticamente desaparece em favor do uso de Aspectos.
Em python, me parece que ambas as coisas podem ser implementadas ou usando metaclasses ou decorators. Mas posso estar errado, já que ainda sei pouco sobre o assunto.
Mas guarde o essencial: não se surpreenda com nomes.
Endereço de trackback para este post
Trackback URL (clique direito e copie atalho/localização do link)


