【问题标题】:Storing methods in a lambda and sending to an object将方法存储在 lambda 中并发送到对象
【发布时间】:2012-12-07 19:01:26
【问题描述】:

如果函数以 lambda 形式存储在变量中,是否可以在对象上调用函数(向其发送消息)?

假设我有一个像 %w(a b c) 这样的数组

然后我可以链接方法,例如:

%w(a b c).reverse.map(&:upcase) # => ["C", "B", "A"] 

是否可以将链接的方法调用提取到一个变量并将它们应用到其他数组对象?

transform = -> { reverse.map(&:upcase) }

我尝试了以下方法,但没有任何运气:

使用 JRuby 1.7.1

%w(a b c).send(transform)
TypeError: #<Proc:0x19a639d8@(irb):12 (lambda)> is not a string

还有

%w(a b c).send(&transform)
ArgumentError: wrong number of arguments (0 for 1)

使用 Ruby 1.9.3

%w(a b c).send(transform)
TypeError: #<Proc:0x007fa0721f0dc8@(irb):1 (lambda)> is not a symbol

%w(a b c).send(&transform)
ArgumentError: no method name given

【问题讨论】:

    标签: ruby jruby ruby-1.9


    【解决方案1】:

    我看到至少两种方法:

    1) 你似乎喜欢用隐式接收器编写 lambdas(我不推荐它,self 显然会改变),你有instance_exec

    transform = -> { reverse.map(&:upcase) }
    ["a", "b", "c"].instance_exec(&transform)
    #=> ["C", "B", "A"]
    

    2) 编写自定义扩展,例如Object#apply:

    class Object
      def apply(block, *args)
        block.call(self, *args)
      end
    end
    
    transform = -> strings { strings.reverse.map(&:upcase) }
    ["a", "b", "c"].apply(transform)
    #=> ["C", "B", "A"]
    

    【讨论】:

    • 感谢您的帮助。使用 instance_eval 会不会 self 不是接收对象?
    • instance_eval 还将对象作为第一个参数发送给块,所以你会得到一个错误(因为 lambda 有 0 个参数)。
    • 德普。我的意思是instance_exec,而不是instance_eval
    • 我不确定我是否理解你的问题,但这就是 instance_eval/instance_exec 的目的,用self 设置一个对象来执行一个块。问题很明显,你有一个闭包(仍然可以访问局部变量,但是self@var等等,改变它的接收者)。
    • 6 岁的答案,刚刚解决了我被阻止超过 3 天的问题
    【解决方案2】:
    class Array
      def transform; reverse.map(&:upcase) end
    end
    
    %w(a b c).send(:transform)
    

    【讨论】:

      猜你喜欢
      • 2015-10-19
      • 2015-11-11
      • 2021-05-07
      • 2021-12-28
      • 2013-08-16
      • 2012-04-20
      • 2018-06-07
      • 1970-01-01
      • 2015-11-19
      相关资源
      最近更新 更多