2011-08-19 7 views
7

Hay un lenguaje común de utilizar como sustituciones:#with (objeto) y truco bloque

def with clazz, &block 
    yield clazz 
    clazz 
end 

with Hash.new |hash| 
    hash.merge!{:a => 1} 
end 

¿Hay una manera de ir más allá y definir #with para tener una posibilidad de hacer:

with Hash.new |hash| 
    merge!{:a => 1} 
end 

o incluso:

with Hash.new do 
    merge!{:a => 1} 
end 

?


ACTUALIZACIÓN

tarde accidentalmente me encontré exactamente lo que estaba buscando (solución similar a la aceptada uno): http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19153

ACTUALIZACIÓN 2

Fue añadida azucarado/dsl en https://github.com/kristianmandrup/sugar-high

ACTUALIZACIÓN 3

docille project on Github explota esta idea muy bien.

+0

¿Por qué? Puedes elegir tu variable de bloque para que sea tan corta como quieras. ¿Qué ahorrarías? Y por cierto, te perdiste 'do'. –

+0

¡Concéntrese en la pregunta, por favor! ¿Es finalmente posible? –

+3

"Hay una expresión común de usar sustituciones como" - '[cita requerida]'. –

Respuesta

7

Si se refiere a la manera en la que los carriles no encaminar entonces creo que hay que hacer algo como esto

def with(instance, &block) 
    instance.instance_eval(&block) 
    instance 
end 

with(Hash.new) do 
    merge!({:a => 1}) 
    merge!({:b => 1}) 
end 

Ésta es la forma en que puedo ver que está siendo hecho en los rieles fuente de todos modos empezar por mirar en el método de sorteo en action_pack/lib/action_dispatch/routing/route_set

3

no es su pseudo-Rubí:

with Hash.new do |hash| 
    merge!{:a => 1} 
end 

El mismo que el uso de 1,9 tap? Por ejemplo:

>> x = Hash[:a, :b].tap { |h| h.merge!({:c => :d}) } 
=> {:a=>:b, :c=>:d} 

Aún debe nombrar el argumento del bloque, por supuesto.

+0

Tienes razón. Son muy similares. Pero quiero evitar las llamadas a la variable pasada al bloque, ¡pero directamente! como Hash [: a,: b] .some_cool_method {merge! ({: c =>: d})} –

1

puede utilizar el rubí incorporado tap:

Hash.new.tap do |hash| 
    hash.merge! a: 1 
end 

Esto incluso puede haber "abusado" por múltiples o bjects:

[one_long_name, another_long_name].tap do |(a,b)| 
    a.prop = b.prop 
end 

Por supuesto tanto no te dan exactamente lo with haría de acuerdo a su ejemplo: El bloque no será evaluado dentro de la instancia del objeto. Pero yo prefiero un montón de usar tap con varios objetos, además de tapself retorno, por lo que se pueden encadenar:

[one_long_name, another_long_name].tap {|(a,b)| a.prop = b.prop }.inspect 
Cuestiones relacionadas