Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/kubernetes/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
包装Ruby函数_Ruby - Fatal编程技术网

包装Ruby函数

包装Ruby函数,ruby,Ruby,我希望能够完全透明地包装任何Ruby进程(包括那些我没有为自己编写源代码的进程),并记录其执行时间 my_proc 也就是说,我想创建一个调用my_proc的proc 上下文/接收者 争论 街区 并打印出调用时的执行时间 例如: my_proc = proc { |*args, &block| p self: self, args: args, block: block } Object.new.instance_eval &my_proc #=> { # :sel

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

my_proc
也就是说,我想创建一个调用
my_proc
的proc

  • 上下文/接收者
  • 争论
  • 街区
  • 并打印出调用时的执行时间


    例如:

    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>
    # }
    
    my_proc=proc{|*args,&block | p self:self,args:args,block:block}
    Object.new.instance\u eval和my\u proc
    #=> {
    #:self=>#,
    #:args=>[#],
    #:block=>nil
    # }
    Object.instance_exec'5',my_proc
    #=> {
    #:self=>对象,
    #:args=>[“5”],
    #:block=>nil
    # }
    我的进程调用(1,2){
    #=> {
    #:self=>main,
    #:args=>[1,2],
    #:block=>#
    # }
    
    然后我想包装它,它的行为应该完全相同:

    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>
    # }
    
    def包裹(prc)
    #这是什么样子的?
    结束
    wrapped_proc=wrapp(我的_proc)
    Object.new.instance\u eval(&wrapped\u proc)
    #花了1秒
    #=> {
    #:self=>#,
    #:args=>[#],
    #:block=>nil
    # }
    Object.instance_exec“5”、&wrapped_proc
    #花了2秒
    #=> {
    #:self=>对象,
    #:args=>[“5”],
    #:block=>nil
    # }
    包装过程调用(1,2){
    #花了3秒
    #=> {
    #:self=>main,
    #:args=>[1,2],
    #:block=>#
    # }
    


    透明函数包装器似乎并不难,但我无法理解这一点。

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

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

    def wrap λ
      λ.singleton_class.prepend(Module.new do
        def call(*args, &cb)
          puts "⇓⇓⇓"
          super
          puts "⇑⇑⇑"
        end
      end)
    end
    
    但是,正如我已经说过的那样,没有调用
    Proc#call
    也没有调用
    Proc#to_Proc
    ,我放弃了


    另一方面,我们可以简单地将λ包装在接收器的上下文中,但无法将块作为参数传递给
    instance\u exec
    ,因为它已经接收到λ本身


    情节越来越复杂。由于我们不能将块作为参数传递给
    实例_exec
    ,因此包装器的使用者也不能。是的,这就解决了任务:

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

    给你。

    你的代码不适合我。你是说
    p self、args、block
    实例评估(&wrapped\u proc)
    ?在第一个示例中,您可能希望
    my_proc
    而不是
    wrapped_proc
    。@mudasobwa:检查我的答案编辑历史记录。这是我发布的第一件事。但是,它不符合包装的条件。@mudasobwa:不,这是克隆:)您肯定熟悉装饰器的概念。那是包装。获取一个新对象(新标识),但是一些功能被委托给包装的对象。当然是这样。然而,它仍然是一个
    委托
    模式,这意味着在这种特殊情况下它仍然是零值。我甚至不能复制OP的未包装示例。“我们包装的消费者也不能”-啊!我怎么没想到@SergioTulentsev坦率地说,我仍在深入研究ruby代码(ruby本身的代码:),试图理解在
    调用中绕过
    Proc#call
    的原因。我找不到。我发布的第一个片段对我来说更有意义。很好的解决方案,第一次尝试也会有意义。UTF-8代码是否正在大型官方Ruby项目中使用?“我们包装器的消费者也不能这样做”不太正确。如果修改self对象,则可以传递self、arg和block<代码>a=Object.new;a、 定义单例法:foo,λ;a、 λ(arg){}
    @EricDuminil-Mike-Perham's是一个大型的官方项目。是的,这更像是一个笑话,但根据我的经验(linux/ext{2,4}),自2000年以来,我从未遇到过UTF8的任何问题,我不断地将这些符号引入我们公司的代码库。例如,使用
    作为“警报方法名称,
    用于内部日志和
    for
    OK
    状态使我的代码既古怪又可爱。另外,rails使用
    作为每个请求的
    params
    中UTF-8的值,请检查日志:)