[編輯:我看到@ sawa完成我的回答。我是對的:這是一個bug!]
當字面空的散列是雙重splatted並且空的散列是變量的值是雙重splatted時,得到不同的結果,在我看來似乎是prima facia證明這是由於Ruby中的錯誤。爲了理解錯誤存在的原因,首先考慮將雙重散列哈希傳遞給方法的原因。
假設我們定義一個方法與一些關鍵字參數:
def my_method(x, a: 'cat', b: 'dog')
[x, a, b]
end
my_method(1)
#=> [1, "cat", "dog"]
的默認值適用於這兩個關鍵字參數。現在嘗試:
my_method(1, a: 2)
#=> [1, 2, "dog"]
現在讓我們使用雙摔散列哈希。
h = { a: 2, b: 3 }
my_method(1, **h)
#=> [1, 2, 3]
這與所需的關鍵字參數(Ruby 2.1+)相同。
def my_method(x, a:, b:)
[x, a, b]
end
my_method(1, **h)
#=> [1, 2, 3]
然而,要使用的雙splatted散列作爲參數,散列不能包含未列出作爲在方法定義參數密鑰。
def my_method(x, a:)
[x, a]
end
h = { a: 2, b: 3 }
my_method(1, **h)
#=> ArgumentError: unknown keyword: b
因此,問題出現了:可以雙splatted空哈希被作爲參數傳遞,考慮到所有的哈希的鍵(無)被包括在方法定義的參數(它本來這種情況下,沒有任何影響)?我們來試試吧。
def my_method(x)
[x]
end
my_method(1, **{})
#=> [1]
是的!
h = {}
my_method(1, **h)
#=> ArgumentError: wrong number of arguments (given 2, expected 1)
不!
這沒有任何意義。所以假設這是一個錯誤,它怎麼會出現?正如OP建議的那樣,我懷疑它可能與Ruby的優化有關。它的空散列是一個文字,在Ruby的代碼中可以比之前處理變量的值更早處理它。我猜測,無論誰寫了早期的代碼,對上面提出的問題都回答「是」,而編寫後者代碼的人回答「否」,或者沒有考慮當時的空散列情況。
如果這個錯誤理論沒有被擊落,那麼OP或其他人應該報告它。
好問題!我學到了很多關於關鍵字的論點。 –