Monkeypatching is Destroying Ruby

Sou fã desse bixo :shock:

De qualquer forma, não daria conflito de classloaders ter e usar a mesma classe duas vezes no mesmo lugar não?

Normalmente quando você carrega a mesma classe por dois classloaders e tenta fazer uma atribuição já pega uma CCE.

Não sei porque mas eu ainda acho a gambiarra do call stack menos bizonha (provavelmente porque eu ainda acho que o AspectJ era uma boa idéia) :stuck_out_tongue:

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

Alguém consegue explicar isso?

T+

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?

Com Rubinius + MultiVM (que não sei a quantas isso anda) deve funcionar parecido não ?

[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

T+

[quote=Proteu Alcebidiano]

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

T+[/quote]

Nesse caso, eu ainda gosto da idéia do binding hierárquico. :smiley:

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) -&gt;
  F = fun (P) -&gt; X(fun (Arg) -&gt; (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() -&gt;
 F=fun (SUM) -&gt; fun (N) -&gt;
  %registrar uma contagem ou qualquer tralha que dê uma chance ao código do bloco, exemplo
  %SUM(N) -&gt; N + SUM(N-1)
  %SUM(1) -&gt; 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.

Algo assim procede ou tou viajando? =D

T+

Olá

Também acho arriscado permitir que isto aconteça.

[]s
Luca

Esse artigo me deixou bem interessado em COP. Pena que a leitura vai ter que esperar um bom tempo na fila…