Ruby 语法: x('foo', y: 'bar', z: 'baz') 可以不同于 x('foo', @yz)?
给定一个方法:
def x(*a)
可以像这样调用它: 与
x('foo', y: 'bar', z: 'baz')
以下不同:
@yz = { y: 'bar', z: 'baz' }
x('foo', @yz)
我问是因为我找到了 I18n.translate 方法,定义为:
def translate(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
key = args.shift
backend = config.backend
locale = options.delete(:locale) || config.locale
handling = options.delete(:throw) && :throw || options.delete(:raise) && :raise # TODO deprecate :raise
raise I18n::ArgumentError if key.is_a?(String) && key.empty?
result = catch(:exception) do
if key.is_a?(Array)
key.map { |k| backend.translate(locale, k, options) }
else
backend.translate(locale, key, options)
end
end
result.is_a?(MissingTranslation) ? handle_exception(handling, result, locale, key, options) : result
end
...使用上述不同方法调用时的行为不同。当传入变量而不是内联哈希时,locale
始终设置为 config.locale
并且内置的语言环境回退机制将被阻止运行(无论是否:locale
存在于哈希变量中。)但是,在 IRB 测试中,我找不到 #x
区分的方法。
我暂时通过将哈希内容复制粘贴到受影响的应用程序中的每个 #translate 调用中来解决这个问题,但肯定会很高兴知道这里发生了什么。
Given a method:
def x(*a)
Can calling it like so:
x('foo', y: 'bar', z: 'baz')
Ever differ from:
@yz = { y: 'bar', z: 'baz' }
x('foo', @yz)
I'm asking because I've found the I18n.translate method, defined as:
def translate(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
key = args.shift
backend = config.backend
locale = options.delete(:locale) || config.locale
handling = options.delete(:throw) && :throw || options.delete(:raise) && :raise # TODO deprecate :raise
raise I18n::ArgumentError if key.is_a?(String) && key.empty?
result = catch(:exception) do
if key.is_a?(Array)
key.map { |k| backend.translate(locale, k, options) }
else
backend.translate(locale, key, options)
end
end
result.is_a?(MissingTranslation) ? handle_exception(handling, result, locale, key, options) : result
end
...behaves differently when called using the different approaches above. When passing in a variable instead of the inline hash, then locale
is always set to config.locale
and the built-in locale fallbacks mechanism is prevented from running (regardless of whether :locale
is present in the hash variable.) Yet, in IRB tests, I can't find a way for #x
to tell the difference.
I've worked around this for the moment by copy-pasting the hash contents into each #translate call in the app affected, but sure would by nice to know what's up here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在每次调用该方法之前,是否将新对象分配给变量?我怀疑不是,并且观察到的错误不是由于它的调用方式,而是由于它对传递的对象做了什么。
也就是说,translate 方法在修改传入的对象时可能会对输入产生副作用。在这种情况下,
options.delete(...)
将产生副作用,可能导致后续调用中出现意外行为:虽然“变量是相同的”变量引用的对象已被悄然毁掉。修复(和“正确”的代码)是消除此类副作用。快乐编码。
Is a new object assigned to the variable before each invocation of the method? I suspect not and that the error observed is not due to how it's called, but rather what it does to the objects passed.
That is, the
translate
method can cause/causes side effects to the input as it modifies an object passed in. In this caseoptions.delete(...)
will create a side-effect that could lead to unexpected behavior in subsequent invocations: while the "variable is the same" the object refered to by the variable has been silently ruined. The fix (and "correct" code) is to remove such side-effects.Happy coding.
不,它们是相同的:
请注意,您使用的语法仅适用于 Ruby 1.9 ,不适用于 1.8
no, they are identical:
Please note that the syntax you're using will only work in Ruby 1.9 , not in 1.8