gpt4 book ai didi

ruby - 包装一个 Ruby 函数

转载 作者:数据小太阳 更新时间:2023-10-29 07:58:47 26 4
gpt4 key购买 nike

我希望能够完全透明地包装任何 Ruby 过程(包括那些我没有为自己编写源代码的过程),并记录其执行时间。

my_proc

也就是说,我想创建一个调用my_proc保存

的proc
  1. 上下文/接收者
  2. 论据
  3. block 。

并打印出调用时的执行时间。


例如:

my_proc = proc { |*args, &block| p self: self, args: args, block: block }

Object.new.instance_eval &my_proc
#=> {
# :self=>#<Object:0x007fd4c985f3e0>,
# :args=>[#<Object:0x007fd4c985f3e0>],
# :block=>nil
# }

Object.instance_exec '5', &my_proc
#=> {
# :self=>Object,
# :args=>["5"],
# :block=>nil
# }

my_proc.call(1, 2) { }
#=> {
# :self=>main,
# :args=>[1, 2],
# :block=>#<Proc:0x007fd4c985e9b8>
# }

然后我想包装它,它的行为应该完全一样:

def wrap(prc)
# what does this look like?
end

wrapped_proc = wrap(my_proc)

Object.new.instance_eval(&wrapped_proc)
# took 1s
#=> {
# :self=>#<Object:0x007fd4c985f3e0>,
# :args=>[#<Object:0x007fd4c985f3e0>],
# :block=>nil
# }

Object.instance_exec '5', &wrapped_proc
# took 2s
#=> {
# :self=>Object,
# :args=>["5"],
# :block=>nil
# }

wrapped_proc.call(1, 2) { }
# took 3s
#=> {
# :self=>main,
# :args=>[1, 2],
# :block=>#<Proc:0x007fd4c985e9b8>
# }

透明函数包装器似乎不难,但我想不通。

最佳答案

这里唯一的技巧是处理 λ.call 传递 block 情况,因为在后一种情况下 Proc# call 未被调用。原文如此。

我的第一个 [错误] 意图只是:

def wrap λ
λ.singleton_class.prepend(Module.new do
def call(*args, &cb)
puts "⇓⇓⇓"
super
puts "⇑⇑⇑"
end
end)
end

但正如我已经说过的,specific_eval既不调用 Proc#call 也不调用 Proc#to_proc,我放弃了。


另一方面,我们可以简单地instance_exec 将 λ 包装在接收器的上下文中,但是没有办法将 block 作为参数传递给instance_exec,因为它本身已经接收到 λ。

情节变厚了。由于我们不能将 block 作为参数传递给 instance_exec,我们包装器的使用者也不能。是的,这解决了任务:

def wrap λ
-> (*args, &cb) do
puts "⇓⇓⇓"
(cb ? λ.call(*args, &cb) : instance_exec(*args, &λ)).tap do |result|
puts result.inspect
puts "⇑⇑⇑"
end
end
end

给你。

关于ruby - 包装一个 Ruby 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40669944/

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