【问题标题】:Provide value for self when using Proc#call使用 Proc#call 时为 self 提供价值
【发布时间】:2014-12-02 06:44:35
【问题描述】:

在 Ruby 中使用 Proc#call 调用 lambda 函数时,self 总是以定义函数时的值结束,而不是调用函数时的值,例如:

$p = lambda { self }

class Dummy
  def test
    $p.call
  end
end

d = Dummy.new

> d.test
=> main

调用test 返回main,而我打算返回的是#<Dummy:0xf794> - Dummy 的一个实例,这是我调用@987654328 的代码中self 的值@。

在 Javascript 中,我只需将我想成为“被调用者”的对象作为第一个参数传递给 call。 Ruby 中是否有任何此类功能,允许我在调用Proc 时将任意对象或至少self 的当前值设置为self 的新值?

【问题讨论】:

  • 我原以为$p.bind(some_object) 可能会起作用,但显然bind 只能与UnboundMethod 对象一起使用。可以将 proc 强制转换为 unboundMethod 吗?

标签: ruby


【解决方案1】:

您正在寻找 instance_eval,它在调用对象的上下文中评估 lambda。

>> $p = proc { self }
=> #<Proc:0x95cece4@(irb):1 (lambda)>
>> class Dummy
>>   def test
>>     $p.call
>>   end
>> 
>>   def test1
>>     instance_eval(&$p)
>>   end
>> end

>> d = Dummy.new
=> #<Dummy:0x946f7c8>
>> d.test
=> main
>> d.test1
=> #<Dummy:0x946f7c8>

【讨论】:

  • 当我尝试以这种方式向instance_eval 发送块时,我总是收到错误ArgumentError: wrong number of arguments (1 for 0)。我认为@shwoodard 的答案现在是正确的答案。
  • 使用proc 而不是lamda 应该可以解决ArgumentError: wrong number of arguments (1 for 0) 异常。
  • 任何解释为什么instance_eval { $p.call }返回main,但instance_eval(&amp;$p)返回实例?
【解决方案2】:

您可能想要使用 instance_exec,因为它允许您将参数传递给块,而 instance_eval 不允许。

def eval_my_proc_with_args(*args, &block)
  instance_exec(*args, &block)
end

【讨论】:

    【解决方案3】:

    lambda 定义了一个闭包,这意味着它将封装它在定义时所拥有的环境。如果您希望 self 成为调用者,只需定义一个常规方法或更好地使用块。

    【讨论】:

    • 谢谢 - 我知道 lambda 创建了一个闭包,我想保留对封装环境的访问权限,但只需覆盖一个特殊变量 self。您对我如何做到这一点有任何想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 2010-12-30
    相关资源
    最近更新 更多