1

最近我想出了这个方法:

module Enumerable
  def transform
    yield self
  end
end

方法的目的类似于tap方法,但具有修改对象的能力。

例如,使用这种方法,我可以更改链式数组中的顺序:

array.do_something.transform{ |a| [a[3],a[0],a[1],a[2]] }.do_something_else

而不是这样做:

a0,a1,a2,a3 = array.do_something
result = [a3, a0, a1, a2].do_something_else

使用此方法时还有其他便利,但是...

该方法非常简单,所以我想某处应该是具有相同目的的已构建方法。

这种红宝石方法有类似物吗?

4

3 回答 3

1

我现在无法对此进行测试,但您应该可以执行以下操作:

array= [1,2,3]
array.tap{ |a| a.clear } 

Tap 运行块然后返回 self 因此如果您可以在块中修改 self ,它将传回更新的数组。在我的示例中, clear 修改块中的 self ,因此返回修改后的 self 。

如果您想要此功能,我建议您添加类似 do_something_else 的方法!修改 self 然后在你的点击块中运行它。

于 2012-06-28T14:24:20.220 回答
1

你可以这样做instance_eval

在接收者的上下文中评估(...)给定的块

例子:

%w(a b c d).instance_eval{|a| [a[3], a[0], a[1], a[2]] }
# => ["d", "a", "b", "c"]

或使用self

%w(a b c d).instance_eval{ [self[3], self[0], self[1], self[2]] }
# => ["d", "a", "b", "c"]
于 2012-06-28T14:29:51.197 回答
0

那么问题在哪里?这完全取决于您想进入函数式编程领域多远。只是阅读Learn You a Haskell for Great Good!,你将永远不会一样。一旦你打开这个 Pandora 盒子,就真的很难停下来,经过一些实验后,我想知道我是否还在编写 Ruby 代码。比较(使用您transform为 定义的方法Object

h = {}
{:a => :a_method, :b => :b_method}.each do |k, m|
  h[k] = some_object.__send__(m)
end
h.some_other_method

some_object.transform(&THash[:a => :a_method, :b => :b_method]).some_other_method

在哪里

THash = 
  lambda do |t| 
    h = {}
    kms = t.map { |k, v| [k, v.to_proc] }
    lambda do |x| 
      kms.each { |k, m| h[k] = m[x] }
    end
  end

因此,如果您想从转换的角度来考虑您的对象,它非常有意义并且确实使代码更具可读性,但它不仅仅是transform方法,您需要定义您经常使用的通用转换。

基本上它被称为point-free编程,尽管有些人称之为pointless。取决于你的心态。

于 2012-06-28T15:21:38.117 回答