2009-09-06 12 views

Respuesta

96

block es solo una variable local, &block es una referencia al bloque pasado al método.

def foo(block = nil) 
    p block 
end 

foo # => nil 
foo("test") # => test 
foo { puts "this block will not be called" } # => nil 

def foo(&block) 
    p block 
end 

foo # => nil 
foo("test") # => ArgumentError: wrong number of arguments (1 for 0) 
foo { puts "This block won't get called, but you'll se it referenced as a proc." } 
# => #<Proc:[email protected]:20> 

También puede utilizar &block cuando se llama a métodos para pasar un proc como un bloque a un método, por lo que se puede utilizar procsos tal como se utiliza bloques.

my_proc = proc {|i| i.upcase } 

p ["foo", "bar", "baz"].map(&my_proc) 
# => ["FOO", "BAR", "BAZ"] 

p ["foo", "bar", "baz"].map(my_proc) 
# => ArgumentError: wrong number of arguments (1 for 0) 

El nombre de la variable block no significa nada especial. Puede usar &strawberries si lo desea, el símbolo comercial es la clave aquí.

Puede que encuentre this article útil.

+28

+1 para '' '& strawberries''' – raycchan

+1

Añadiré: es similar a cómo se usa el operador splat (es decir, '*') para arreglos:' def foo (* args) ; other_foo (* args); end' tomará una matriz arbitraria de argumentos, y luego pasará esa misma matriz a la llamada de función interna. Con bloques, harías 'def foo (& block); other_foo (y bloque); fin –

27

En una lista de argumentos, &whatever toma el bloque que se pasó al método y lo envuelve en un objeto Proc. El Proc se almacena en una variable llamada whatever (donde puede ser cualquier nombre que haya tipeado después del signo y, por supuesto, generalmente es "bloque"). Después de una llamada a un método, la sintaxis &whatever convierte un Proc en un bloque. Así que si se define un método de este modo:

def thing(&block) 
    thing2 &block 
end 

se está definiendo un método que toma un bloque y luego llama a otro método con ese bloque.

16

Si no configura el & antes del bloque, Ruby no reconocerá su relación con el "bloque" que pasa a la función. Aquí algunos ejemplos.

def f(x, block); end 
f(3) { 2+2 } # gives an error, because "block" is a 
       # regular second argument (which is missing) 

def g(x, &block); end 
g(3) { 2+2 } # legal 

def h(x); end 
h(3) { 2+2 } # legal 

para su uso posterior en una función:

def x(&block) # x is a 0 param function 
    y(block)  # y is a 1 param function (taking one "Proc") 
    z(&block)  # z is a 0 param function (like x) with the block x received 
end 

Por lo tanto, si se llama a z(&block) es (casi !!) lo mismo que llamar z { yield }: Usted sólo tiene que pasar el bloque a la siguiente función.

Cuestiones relacionadas