当默认值为空哈希值时,如何解释默认参数

时间:2014-07-11 23:28:37

标签: ruby-on-rails ruby hash

我正在阅读这个问题:https://stackoverflow.com/a/4402761/2379703,显示rails render impl的最后一篇文章很有意思。它的签名是:

def render(options = {}, locals = {}, &block)

如果第一个参数是一个普通字符串,它会将它分配给选项,其余的被解释为一个哈希并分配给本地。例如:

render('partial_name', key: 'value', key2:, 'value2')

结果是:

options = "partial_name"
locals = {key: 'value', key2:, 'value2'}

如果你只是传递键/值对,它假设你传递了一个哈希的单个参数并将它全部分配给选项并将本地空置为空:

render(partial: 'partial_name', key: 'value', key2", 'value2')

结果是:

options = {partial: 'partial_name', key: 'value', key2:, 'value2'}
locals = {}

所以我的问题归结为:当有多个可选参数时,ruby使用什么逻辑来确定哪个参数被赋值?此外,似乎哈希使得这个问题的答案更有趣,因为当作为参数传入时,哈希显然不需要与外部{}分隔。

第二次观察,在测试中,我使用相同的签名作为渲染等测试方法,并通过了以下内容:

render(key: 'value', key2: 'value2', 'string')

这会导致语法错误:

test_hash_param.rb:15: syntax error, unexpected ')', expecting =>

这是为什么?为什么不将两个键/值对分配给选项并将本地设置为' string'?

然而,这可行,因为我认为它会:

render({key: 'value', key2: 'value2'}, 'string')

2 个答案:

答案 0 :(得分:1)

首先,您只能将没有{}括号的哈希作为方法的最后一个参数传递。否则,解释者要找出一个参数的结束位置和另一个参数的开始将会更加困难。

说到这里,当ruby在参数列表的末尾看到一个类似哈希的参数列表时,它总是将它视为单个哈希。因此,在您的示例中,只有选项具有赋值,因为尚未传递本地并且已使用默认值。你可以在这里找到很多关于stackoverflow的问题。如果你需要传递两个单独的哈希值,你需要在括号中包含至少第一个哈希值(当然,如果它不是最后一个参数,则自然地包含第二个哈希值)

答案 1 :(得分:1)

因为你传递的哈希没有边界,所以ruby必须决定如何解释它们。而不是选择一个任意的地方将你的key:value对分成两个哈希,它只是将它们全部分成一个哈希。这意味着:

render( foo: "bar", hello: "world", "bananas")

被读取为一个哈希,因为它无法分辨您希望结束哈希的位置。 'bananas'作为键包含在内(因为字符串可以是键)并弹出语法错误,因为您没有为其赋值。

选项和局部函数不一定是哈希值,因为ruby变量类型是动态的。它们的默认值是一个空哈希,但是如果你传递两个字符串,它们都将被分配字符串。当你传递一个字符串时,它被分配给选项,因为它是一个完整的变量。当你传递一个符号/字符串和一个哈希火箭(或者一个带有冒号的符号翻转)时,你告诉ruby“这是一个哈希的开头”,所以它开始寻找键:值对。为了在你的参数结束之前结束那个哈希以便你可以传递另一个参数,你必须明确告诉ruby停止寻找key:value对。