像tap这样的组合方法,但能够返回不同的值?
我正在经历一个尝试避免临时变量和过度使用条件的阶段,在这个阶段我可以使用更流畅的编码风格。我非常喜欢在想要获取需要返回的值的地方使用 #tap
,但在返回它之前先对其执行一些操作。
def fluid_method
something_complicated(a, b, c).tap do |obj|
obj.update(:x => y)
end
end
对比。过程:
def non_fluid_method
obj = something_complicated(a, b, c)
obj.update(:x => y)
obj # <= I don't like this, if it's avoidable
end
显然上面的例子很简单,但这仍然是 Ruby 社区中非常常见的编码风格。我有时也会使用#inject 通过一系列过滤器传递对象
things.inject(whatever) do |obj, thing|
thing.filter(obj)
end
:程序:
obj = whatever
things.each do |thing|
obj = thing.filter(obj)
end
obj
现在我面临着重复使用如下所示的条件,并寻找一种更流畅的方法来处理它:(
def not_nice_method
obj = something_complex(a, b, c)
if a_predicate_check?
obj.one_more_method_call
else
obj
end
end
稍微)更干净的解决方案是以重复为代价避免临时变量:
def not_nice_method
if a_predicate_check?
something_complex(a, b, c).one_more_method_call
else
something_complex(a, b, c)
end
end
我不能不过,我还是想在这里使用几乎类似#tap
的东西。
我在这里还可以遵循哪些其他模式。我意识到这对某些人来说只是无意义的糖,我应该转向更有趣的问题,但我正在尝试学习以更实用的风格编写,所以我只是好奇长期的红宝石主义者已经确定了什么是解决此类情况的好方法。这些例子被大大简化了。
I'm going through a phase of trying to avoid temporary variables and over-use of conditional where I can use a more fluid style of coding. I've taken a great liking to using #tap
in places where I want to get the value I need to return, but do something with it before I return it.
def fluid_method
something_complicated(a, b, c).tap do |obj|
obj.update(:x => y)
end
end
Vs. the procedural:
def non_fluid_method
obj = something_complicated(a, b, c)
obj.update(:x => y)
obj # <= I don't like this, if it's avoidable
end
Obviously the above examples are simple, but this is a pretty common coding style in the ruby community nonetheless. I'll sometimes use #inject
to pass an object through a series of filters too:
things.inject(whatever) do |obj, thing|
thing.filter(obj)
end
Vs. the procedural:
obj = whatever
things.each do |thing|
obj = thing.filter(obj)
end
obj
Now I'm facing repeated use of a condition like the following, and looking for a more fluid approach to handling it:
def not_nice_method
obj = something_complex(a, b, c)
if a_predicate_check?
obj.one_more_method_call
else
obj
end
end
The (slightly) cleaner solution is to avoid the temporary variable at the cost of duplication:
def not_nice_method
if a_predicate_check?
something_complex(a, b, c).one_more_method_call
else
something_complex(a, b, c)
end
end
I can't help but feeling the desire to use something almost like #tap
here though.
What other patterns might I follow here. I realise this is all just nonsensical sugar to some people and that I should just move onto more interesting problems, but I'm trying to learn to write in a more functional style, so I'm just curious what long-term rubyists have determined to be good ways to tackle situations like this. These examples are hugely simplified.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
定义
Object#as
:现在你可以写:
Define
Object#as
:And now you can write:
神奇之处在于
tap
中的break
返回另一个值。new
ruby 2.5 有
yield_self
这正是你想要的。https://stackoverflow.com/a/47890832/683157
The magic is
break
intap
returns another value.new
ruby 2.5 has
yield_self
which exactly you want.https://stackoverflow.com/a/47890832/683157
instance_eval
可能会被滥用于此目的"this".instance_eval { |test|测试+“有效”}
从 2.5 开始,可以使用
yield_self
"easy".yield_self{ |a| a + " peasy" }
阅读更多:
https://ruby-doc.org/core-1.9.3/BasicObject.html#method-i-instance_eval
https://ruby-doc.org/core-2.5.0 /Object.html#method-i-yield_self
instance_eval
can be misused for this purpose"this".instance_eval { |test| test + " works" }
since 2.5 it is possible to use
yield_self
"easy".yield_self{ |a| a + " peasy" }
Read more:
https://ruby-doc.org/core-1.9.3/BasicObject.html#method-i-instance_eval
https://ruby-doc.org/core-2.5.0/Object.html#method-i-yield_self
我在 Facets gem 中找到了一个可能正是您正在寻找的方法: Kernel#ergo
所以你原来的方法:
最终可能看起来像这样:
I found a method in the Facets gem that might be what you were looking for: Kernel#ergo
So your original method:
might end up looking something like this:
我需要做这样的事情,我喜欢托克兰的答案,但我不想因为我正在编写的小脚本而污染对象。相反,我在数组上使用了
tap
:I needed to do something like this and I like tokland's answer, but I didn't want to pollute Object for the small script I was writing. Instead, I made use of
tap
on an array:典型用法:
您的情况:
甚至
Typical usage:
Your case:
or even