【问题标题】:#with(object) &block trick#with(object) &block 技巧
【发布时间】:2011-10-30 06:31:03
【问题描述】:

有一个使用替换的常见习惯用法,例如:

def with clazz, &block
  yield clazz
  clazz
end

with Hash.new |hash|
  hash.merge!{:a => 1}
end

有没有办法更进一步,定义#with 有可能做:

with Hash.new |hash|
  merge!{:a => 1} 
end

甚至:

with Hash.new do
  merge!{:a => 1}
end

?


更新

后来我偶然发现了我正在寻找的东西(类似于接受的解决方案): http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19153

更新 2

它被添加到https://github.com/kristianmandrup/sugar-high中的sugar-high/dsl

更新 3

docille project on Github 很好地利用了这个想法。

【问题讨论】:

  • 有什么用?您可以选择尽可能短的块变量。你会保存什么?顺便说一句,你错过了do
  • 请关注问题!终于可以了吗?
  • “有一个使用替换的常见习惯用法,例如” - [citation needed]
  • 您想要实现的最后一件事是可能的(通过 instance_eval),但它会产生一些问题:这个块将不再被视为闭包,它将被不同的绑定调用。这样的代码很容易开始变得不可读。
  • "...这个块将不再被视为闭包,它将被不同的绑定调用"。你能更详细地解释一下吗?或者举个例子......我知道 instance_eval 给出了限制,但我认为那些将使用这种 #with 方法的人理解它们。也许我忽略了什么?

标签: ruby idioms


【解决方案1】:

如果您指的是 Rails 进行路由的方式,那么我认为您需要做这样的事情

def with(instance, &block)
  instance.instance_eval(&block)
  instance
end

with(Hash.new) do
  merge!({:a => 1})
  merge!({:b => 1})
end

这就是我在 Rails 源代码中看到它的方式,首先查看 action_pack/lib/action_dispatch/routing/route_set 中的 draw 方法

【讨论】:

    【解决方案2】:

    不是你的伪 Ruby:

    with Hash.new do |hash|
      merge!{:a => 1} 
    end
    

    和使用 1.9 的 tap 一样吗?例如:

    >> x = Hash[:a, :b].tap { |h| h.merge!({:c => :d}) }
    => {:a=>:b, :c=>:d}
    

    当然,你仍然需要命名 block 参数。

    【讨论】:

    • 你是对的。它们非常相似。但是我想避免调用传递给块的变量,而是直接调用!像 Hash[:a, :b].some_cool_method { merge!({:c => :d}) }
    【解决方案3】:

    您可以使用 ruby​​ 内置 tap:

    Hash.new.tap do |hash|
      hash.merge! a: 1
    end
    

    这甚至可能被多个对象“滥用”:

    [one_long_name, another_long_name].tap do |(a,b)|
      a.prop = b.prop
    end
    

    当然,根据您的示例,两者都不能准确地告诉您 with 会做什么:不会在对象实例中评估该块。但是我更喜欢将tap与多个对象一起使用,加上tap返回self,因此可以链接:

    [one_long_name, another_long_name].tap {|(a,b)| a.prop = b.prop }.inspect
    

    【讨论】:

      猜你喜欢
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 1970-01-01
      • 2010-11-10
      • 2010-09-13
      • 2011-07-18
      • 2018-05-26
      相关资源
      最近更新 更多