String对象上的'tap'方法不返回预期结果

Har*_*tty 12 ruby-on-rails

我在'String'类型的对象上使用'tap'方法时遇到了一个有趣的问题.

"abc".tap { |o| o = "xyz" } # this line returns "abc" instead of "xyz"
Run Code Online (Sandbox Code Playgroud)

'tap'方法适用于其他类型的对象.

[].tap { |o| o << "xyz" } # this line returns ["xyz"] as expected
Run Code Online (Sandbox Code Playgroud)

我在Windows XP上使用Rails 2.3.2和Ruby 1.8.6.

我在这里错过了什么?

更新1:我解决了这个问题.这是我的使用错误.在第一个场景中,我将值重新分配给块参数而不是修改它.我能够重写代码并获得预期的结果.

"abc".tap { |o| o.replace "xyz" }
Run Code Online (Sandbox Code Playgroud)

更新2:此处使用的代码仅用于演示问题.我的实际代码看起来不像这样.

Joh*_*ata 8

Object#tap总是返回执行块后传入其中的原始对象,即使该块返回不同的内容.

这里的好处是您可以将tap放入链的中间并测试对象的值而无需修改原始值.

这意味着如果你将"abc"传递给tap,它将执行该块并返回"abc".你对o的任务并不意味着任何由于范围界定的事情.同样,如果将空数组传递给tap,它将返回一个空数组.但是,在第二个示例中,您修改了原始值.修改原始操作,如<<或gsub!或者同样会在返回之前修改对象,因此您将获得不同的值.

查看http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions,了解一些关于如何使用tap的更酷的例子.不要用它来进行任务或修改,否则你会收到不稳定的结果.

更新:要进行编辑,为什么会解决您的问题?我不明白为什么当你可以在对象本身上调用replace时,你会调用tap来进行替换.为您提供什么好处?

  • 是的,使用'tap'进行简单的替换是没有意义的.我的实际代码看起来不像这样.我没有发布大量的代码,而是想出了这个例子来重现这个问题.我倾向于使用'tap'进行调试.最近我开始使用'tap'代替'return'.一旦我重新阅读了tap方法的Rails源代码,我的错误就变得明显了. (2认同)