Ruby: LocalJumpError - PullRequest
       5

Ruby: LocalJumpError

1 голос
/ 08 ноября 2019

Почему я получаю сообщение об ошибке:

ОШИБКА:

LocalJumpError
# ~> no block given (yield)

КОД:

module M
  def hello(text = 'bba')
    puts "yo-#{text}"      # => nil
  end                      # => :hello

  instance_methods  # => [:hello]

  m = instance_method(:hello)  # => #<UnboundMethod: M#hello>

  define_method(:bye) do |*args, &block|  
    yield                                 # ~> LocalJumpError: no block given (yield)
    m.bind(self).(*args, &block)
  end                                     # => :bye

end  # => :bye

class A
  include M  # => A
end          # => A


A.new.hello('vv')       # => nil
A.new.bye('zz') do |p|  # => #<A:0x00007fa8c401e090>
  puts "ggg"
end

# >> yo-vv

# ~> LocalJumpError
# ~> no block given (yield)

1 Ответ

4 голосов
/ 08 ноября 2019

Это разница в семантике def и define_method. Смотрите это:

module M
  def outer(&block)
    puts "outer: #{yield}"

    def inner1
      puts "inner1: #{yield}"
    end

    M.define_method(:inner2) do
      puts "inner2: #{yield}"
    end

    M.define_method(:inner3) do |&block|
      puts "inner3: #{block.call}"
    end

    inner1 { 1 }
    inner2 { 2 }
    inner3 { 3 }
  end
end

class A
  include M
end

A.new.outer { 0 }
# => outer: 0
#    inner1: 1
#    inner2: 0 (!!!)
#    inner3: 3

yield работает только внутри def.

Таким образом, inner1 вызывает свой собственный блок;но inner2 использует блок def, в котором он находится. Правильный способ вызвать блок внутри define_method - захватить его в списке параметров (как вы это сделали), а затем использовать #call или #[] на нем, как показывает inner3.

В вашем коде нет def вокруг, поэтому при вашем yield блок недоступен. Вы можете использовать вышеуказанный метод и заменить yield на block.call.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...