Desculpe a ignorância, mas por que AspectJ não seria considerada uma boa idéia nesses dias?
Pergunto porque este mês comecei a estudar POA com AspectJ…
[quote=tnaires]Desculpe a ignorância, mas por que AspectJ não seria considerada uma boa idéia nesses dias?
Pergunto porque este mês comecei a estudar POA com AspectJ…[/quote]
Porque a necessidade de uma ferramenta de AOP pra fazer alguma coisa é um sinal de que a linguagem não oferece facilidades pra alteração das definições de objetos e classes em tempo de execução boas ou simples o suficiente.
Hum…acho que se voce transformar o seu bloco numa proc atraves de lambda e em seguida dar um call na proc, resolve o problema:
A sugestão para a bazooka procedeu sem problemas
def fire(&block)
lambda(&block).call(instance_eval(&block))
end
e para as risadas malevolentes:
def huhuhu(&block)
lambda(&block).call(instance_eval(&block))
end
Só tem uma coisa que não entendi, para a segunda sugestão que passei, ele retorna
nil
"risada maquiavelica"
122
test.rb:7:in `hehe': undefined local variable or method `bwawawawawa' for #<A:0x2ae5c0c @abc=122> (NameError)
from test.rb:13:in `call'
from test.rb:13:in `huhuhu'
from test.rb:7:in `hehe'
from test.rb:21
porque diabos a saida está assim, acusando erro de escopo mesmo imprimindo o valor do referido método? e porque a ordem de impressão dos atributos ficou invertida?
pior nem é isso. Quando eu inverto os valores em
def hehe
B.new.huhuhu{p bwawawawawa; p @abc}
end
ele imprime:
"risada maquiavelica"
nil
test.rb:7:in `hehe': undefined local variable or method `bwawawawawa' for #<A:0x2ae5c0c @abc=122> (NameError)
from test.rb:13:in `call'
from test.rb:13:in `huhuhu'
from test.rb:7:in `hehe'
from test.rb:21
>Exit code: 1
Glaucio, você está executando o mesmo bloco várias vezes, não? A idéia é executar uma vez só e ter acesso aos métodos necessários nesta execução. Executar o mesmo bloco diversas vezes é inviável na maioria dos cenários para uma linguagem não funcional (que tem estado mútavel).
[quote=pcalcado]São dois problemas. Um é a falta de opções de binding, fazendo com que eu tenha quea alterar classes (adicionar métodos em inteiros) quando o que eu queria era simplesmente que um método estivesse disponivel em um contexto qualquer. Outro é o fato de que se eu alterar uma classe (como consequência do primeiro ou não) eu altero ela em todo o sistemas.
Será que JRuby não consegue resolver o seundo problema com classloaders diferentes? Não tenho idéia, não sei como o JRuby funciona… LOOOOOOOOOOOOOOUUUUUDS!!![/quote]
Se não me engano, cada classe Ruby vira um objeto de verdade na JVM. Instância de RubyClass, ou algo do tipo.
Não precisa de vários ClassLoaders pq não é estático. Bastaria fazer com que os escopos pudessem estar associados a versões modificadas do RubyClass original. Isso não deve ser muito difícil de fazer, mas eu acho que a chance de fazerem deve ser perto de nula, já que isso faria com que o JRuby não fosse compatível com o MRI.
De qq forma, acho que vale um papo com o Nutter e cia no #jruby @ freenode, ou na lista do jruby-dev.
[quote=pcalcado]Glaucio, você está executando o mesmo bloco várias vezes, não? A idéia é executar uma vez só e ter acesso aos métodos necessários nesta execução. Executar o mesmo bloco diversas vezes é inviável na maioria dos cenários para uma linguagem não funcional (que tem estado mútavel).
Btw, alguém implementa uma gambi com currying?[/quote]
Opa,
você tem razão, o que propus parecia trapaça para solucionar o problema, e o que é pior, nem currying para isso funciona direito porque lambda tenta processar o bloco com tudo o que tiver dentro dele o_O
O ponto é: lambda.call enxerga o escopo de A e tenta evocar o de B (dando a tal unresolved variable), instance_eval enxerga o escopo de B e não enxerga o de A.
De todo modo, o problema da bazooka pode se resumir a:
def fire(&block)
lambda(&block).call
end
No caso do exemplo das risadas, não sei como proceder…nao sei como, mas se lambda pudesse aceitar algo tipo:
def fire(&block)
lambda(&block, self).call #arrumem uma notação melhor :D
end
Seria interessante, pois poderiamos fazer o bloco enxergar o escopo externo ao bloco
Fiquei pesando no seguinte, da mesma forma que se usa o Ycomb para implementar recursão em um lambda, será que não existe como derivar o fix point dos bindings e, ao ir adiante, ir chamando tudo via algo semelhante ao Ycomb?
[quote=louds]Fiquei pesando no seguinte, da mesma forma que se usa o Ycomb para implementar recursão em um lambda, será que não existe como derivar o fix point dos bindings e, ao ir adiante, ir chamando tudo via algo semelhante ao Ycomb?
[/quote]
Rapaz, usando a idéia de combinators em bindings seria interessante porque voce poderia mudar a regra de binding sem precisar modificar o runtime da linguagem, e considerando que bindings realizam ações (funçoes) de referência, poderia-se criar uma high-order function para bindings…algo tipo, numa implementaçao de Y-comb (pegar uma implementação em erlang, pra facilitar a leitura)
y(X) ->
F = fun (P) -> X(fun (Arg) -> (P(P))(Arg) end) end,
F(F).
voce ter uma funcao de counting ou binding regstry, que seria acionada pelo analisador a cada vez que um comando dentro de um bloco não estivesse definido no escopo mais "raso" do código:
% chamem o rapazinho aqui para registrar bindings
count_binding() ->
F=fun (SUM) -> fun (N) ->
%registrar uma contagem ou qualquer tralha que dê uma chance ao código do bloco, exemplo
%SUM(N) -> N + SUM(N-1)
%SUM(1) -> N.
end,
end
y(F).
ou então, se não quiser fazer algo hierárquico, colocar numa hash ou lista ao invés de um contador.