代码之家  ›  专栏  ›  技术社区  ›  Karol Selak

如何在另一个lambda体内“粘合”lambda?

  •  1
  • Karol Selak  · 技术社区  · 7 年前

    假设我有两个红宝石羔羊:

    lambda1 = -> { puts 'lambda1' }
    lambda2 = -> {
      puts 'lambda2 calls lambda1'
      lambda1.()
    }
    

    它按预期工作:

    lambda1.()
    # lambda1
    lambda2.()
    # lambda2 calls lambda1
    # lambda1
    

    但现在如果我移除 lambda1 , lambda2 将停止工作:

    lambda1 = nil
    lambda2.()
    

    nomethoderror:nil的未定义方法“call”:nilclass

    我能做什么来“粘”我的 λ1 λ2 使第一个成为第二个的固有部分并避免这种情况?

    1 回复  |  直到 7 年前
        1
  •  5
  •   Max    7 年前

    问题是你的 lambda2 捕获变量 lambda1 在结束时,它会注意到 λ1 稍后更改。解决方案是让它捕获一个不同的变量:

    lambda1 = -> { puts 'lambda1' }
    x = lambda1 # copy the reference
    lambda2 = -> { x.() }
    lambda1 = nil
    lambda2.()
    

    “但这也有同样的问题!”你可能会说,“我可以通过重新分配 x “那就这样吧 X 受作用域保护:

    def wrap x
      -> { x.() }
    end
    
    lambda1 = -> { puts 'lambda1' }
    lambda2 = wrap lambda1
    lambda1 = nil
    lambda2.()