Ruby中是否有一个返回传递给对象的块内容的方法?
例如,如果我有一个想要放入数组的对象怎么办?
在一个理想的世界里,我们会做(我正在寻找的):
"string".reverse.upcase.something{ |s| send(s) }
将使用我的对象返回一个数组,相当于:
send("string".reverse.upcase)
如果我的对象开始时是不可链接的,并且在更复杂的场景中会变得混乱。
因此something
方法将返回块的评估,如Array#map
,但仅返回一个元素。
答案 0 :(得分:4)
我不知道内置这样的东西,但你可以自己轻松做到:
class Object
def something(&block)
block.call(self)
end
end
p "foo".something { | o | [o] }
p 23.something { | x | p x; 42 }
给出
["foo"] # object "foo" put into an array
23 # object handed to block
42 # something return block's result
答案 1 :(得分:1)
您在寻找Object.tap吗?
答案 2 :(得分:1)
我有时希望标准库中有类似的功能。例如,该名称可以是with
或with_it
(使用新名称重复以前的代码)
class Object
def with_it(&block)
block.call(self)
end
end
使用示例:
x = [1, 2, 3, 4, 5].map {|x| x * x }.with_it do |list|
head = list.unshift
list << head * 10
list.join " / "
end
相反:
list = [1, 2, 3, 4, 5].map {|x| x * x }
head = list.unshift
list << head * 10
x = list.join " / "
虽然后者更容易理解,但前者的好处是保留变量list
和head
作用域,而x
的作业在我看来更明确(作业)必须将x
插入到代码的最后一行)。如果代码是更大方法的一部分,那么范围界定将是一个不错的选择。
使用with_it
的另一个选择是将代码放在一个单独的方法中。例如:
def mult_head_and_join(list)
head = list.unshift
list << head * 10
list.join " / "
end
x = mult_head_and_join [1, 2, 3, 4, 5].map {|x| x * x }
不知道在这里结束什么,但我想我会投票支持将with_it纳入标准库
答案 3 :(得分:1)
在原始问题发布六年后,Ruby 2.5.0引入了 Object#yield_self
,然后在Ruby 2.6中缩短为 #then
:
class Object def yield_self(*args) yield(self, *args) end end
[...]
执行块并返回其输出。
例如:
2.then{ |x| x*x } # => 4