加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

理解从Ruby中的procs返回

发布时间:2020-12-16 21:05:23 所属栏目:百科 来源:网络整理
导读:我想知道如何将一个块传递给一个方法,该方法将使该方法返回yield. 天真的方法不起作用: def run(block) block.callendrun { return :foo } # = LocalJumpError 包装在另一个proc中具有相同的效果: def run(block) proc { block.call }.callendrun { return
我想知道如何将一个块传递给一个方法,该方法将使该方法返回yield.

天真的方法不起作用:

def run(&block)
  block.call
end

run { return :foo } # => LocalJumpError

包装在另一个proc中具有相同的效果:

def run(&block)
  proc { block.call }.call
end

run { return :bar } # => LocalJumpError

所以我认为return语句绑定到当前绑定的接收者.但是,尝试使用instance_eval证明我错了:

class ProcTest
  def run(&block)
    puts "run: #{[binding.local_variables,binding.receiver]}"
    instance_eval(&block)
  end
end

pt = ProcTest.new
binding_inspector = proc { puts "proc: #{[binding.local_variables,binding.receiver]}" }
puts "main: #{[binding.local_variables,binding.receiver]}"
    # => main: [[:pt,:binding_inspector],main]
binding_inspector.call
    # => proc: [[:pt,main]
pt.run(&binding_inspector)
    # => run: [[:block],#<ProcTest:0x007f4987b06508>]
    # => proc: [[:pt,#<ProcTest:0x007f4987b06508>]
pt.run { return :baz }
    # => run: [[:block],#<ProcTest:0x007f4987b06508>]
    # => LocalJumpError

所以问题是:

>怎么做到这一点?
>返回上下文如何与return语句绑定.这个连接是否可以通过语言的API访问?
>这是故意以这种方式实施的吗?如果是 – 为什么?如果不是 – 修复它的障碍是什么?

解决方法

I thought that the return statement is bound to the receiver of the current binding.

只有方法有接收器. return不是一种方法:

defined? return #=> "expression"

尝试将其作为方法调用不起作用:

def foo
  send(:return,123)
end

foo #=> undefined method `return'

trying it out with instance_eval proved me wrong

虽然instance_eval在接收器的上下文中评估块(因此您可以访问接收器实例方法和实例变量):

class MyClass
   def foo(&block)
     @var = 123
     instance_eval(&block)
   end
end

MyClass.new.foo { instance_variables }
#=> [:@var]

…它不会评估当前绑定中的块(因此您无权访问任何局部变量):

class MyClass
   def foo(&block)
     var = 123
     instance_eval(&block)
   end
end

MyClass.new.foo { local_variables }
#=> []

How can this be done?

您可以使用eval,但这需要一个字符串:

def foo
  var = 123
  eval yield
  nil
end

foo { "return var * 2" }
#=> 246

或者通过将绑定传递给块(再次使用eval):

def foo
  var = 123
  yield binding
  nil
end

foo { |b| b.eval "return var * 2" }
#=> 246

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读