Разница между блок и и блок в Ruby
Почему иногда я должен использовать блок и другие времена и блок внутри функций, которые принимают блоки?
3 ответа:
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:0x0000000100124ea8@untitled: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
если вам нравится, амперсанд является здесь ключевой.вы можете найти в этой статье полезная.
в списке аргументов,
&whatever
берет блок, который был передан методу, и обертывает его в объект Proc. Proc хранится в переменной с именемwhatever
(где это может быть любое имя, которое вы ввели после амперсанда, конечно - обычно это "блок"). После вызова метода,&whatever
синтаксис превращает Proc в блок. Поэтому, если вы определяете метод следующим образом:def thing(&block) thing2 &block end
вы определяете метод, который принимает блок, а затем вызывает другой метод с этим блоком.
если вы не установите блок & 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 }
: вы просто передаете блок в следующую функцию.