Почему иногда я должен использовать блок и другое время и блок внутри функций, которые принимают блоки?
Разница между блоком и блоком в Ruby
Ответ 1
block
является только локальной переменной, &block
является ссылкой на блок, переданный методу.
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>
Вы также можете использовать &block
при вызове методов для передачи proc как блока метода, чтобы вы могли использовать procs так же, как вы используете блоки.
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)
Имя переменной block
не означает ничего особенного. Вы можете использовать &strawberries
, если хотите, амперсанд - это ключ.
Вы можете найти эту статью.
Ответ 2
В списке аргументов &whatever
принимает блок, который был передан методу, и завершает его в объекте Proc. Proc хранится в переменной с именем whatever
(где это может быть любое имя, которое вы вводили после амперсанда, конечно - обычно это "блок" ). После вызова метода синтаксис &whatever
превращает Proc в блок. Поэтому, если вы определите такой метод:
def thing(&block)
thing2 &block
end
Вы определяете метод, который принимает блок, а затем вызывает другой метод с этим блоком.
Ответ 3
Если вы не установите блок before и раньше, Ruby не узнает его отношение к "блоку", который вы передаете функции. Вот несколько примеров.
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
Для последующего использования в функции:
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
Итак, если вы вызываете z(&block)
его (почти!!) так же, как и вызов z { yield }
: вы просто передаете блок следующей функции.