gpt4 book ai didi

ruby - 如何调用在不同上下文中获取 block 的 Proc?

转载 作者:数据小太阳 更新时间:2023-10-29 06:39:39 24 4
gpt4 key购买 nike

以这个例子为例:

proc = Proc.new {|x,y,&block| block.call(x,y,self.instance_method)}

它有两个参数,x 和 y,还有一个 block 。

我想为自己使用不同的值来执行该 block 。像这样的东西几乎可以工作:

some_object.instance_exec("x arg", "y arg", &proc)

但是,这不允许您传入一个 block 。这也行不通

some_object.instance_exec("x arg", "y arg", another_proc, &proc)

也没有

some_object.instance_exec("x arg", "y arg", &another_proc, &proc)

我不确定还有什么可以在这里工作。这可能吗?如果可以,您是怎么做到的?

编辑:基本上,如果您可以通过更改 change_scope_of_proc 方法让此 rspec 文件通过,您就解决了我的问题。

require 'rspec'

class SomeClass
def instance_method(x)
"Hello #{x}"
end
end

class AnotherClass
def instance_method(x)
"Goodbye #{x}"
end

def make_proc
Proc.new do |x, &block|
instance_method(block.call(x))
end
end
end

def change_scope_of_proc(new_self, proc)
# TODO fix me!!!
proc
end

describe "change_scope_of_proc" do
it "should change the instance method that is called" do
some_class = SomeClass.new
another_class = AnotherClass.new
proc = another_class.make_proc
fixed_proc = change_scope_of_proc(some_class, proc)
result = fixed_proc.call("Wor") do |x|
"#{x}ld"
end

result.should == "Hello World"
end
end

最佳答案

要解决这个问题,您需要将 Proc 重新绑定(bind)到新类。

这是您的解决方案,利用了 Rails core_ext 中的一些优秀代码:

require 'rspec'

# Same as original post

class SomeClass
def instance_method(x)
"Hello #{x}"
end
end

# Same as original post

class AnotherClass
def instance_method(x)
"Goodbye #{x}"
end

def make_proc
Proc.new do |x, &block|
instance_method(block.call(x))
end
end
end

### SOLUTION ###

# From activesupport lib/active_support/core_ext/kernel/singleton_class.rb

module Kernel
# Returns the object's singleton class.
def singleton_class
class << self
self
end
end unless respond_to?(:singleton_class) # exists in 1.9.2

# class_eval on an object acts like singleton_class.class_eval.
def class_eval(*args, &block)
singleton_class.class_eval(*args, &block)
end
end

# From activesupport lib/active_support/core_ext/proc.rb

class Proc #:nodoc:
def bind(object)
block, time = self, Time.now
object.class_eval do
method_name = "__bind_#{time.to_i}_#{time.usec}"
define_method(method_name, &block)
method = instance_method(method_name)
remove_method(method_name)
method
end.bind(object)
end
end

# Here's the method you requested

def change_scope_of_proc(new_self, proc)
return proc.bind(new_self)
end

# Same as original post

describe "change_scope_of_proc" do
it "should change the instance method that is called" do
some_class = SomeClass.new
another_class = AnotherClass.new
proc = another_class.make_proc
fixed_proc = change_scope_of_proc(some_class, proc)
result = fixed_proc.call("Wor") do |x|
"#{x}ld"
end
result.should == "Hello World"
end
end

关于ruby - 如何调用在不同上下文中获取 block 的 Proc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9871185/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com