2015-01-18 7 views
5

Ich habe eine Methode wie folgt definiert:Kann dieser Ruby-Methodenaufruf ohne ** {} am Ende gemacht werden?

def woot(a = nil, b: nil) 
    ... 
end 

Was die am wenigsten hässliche Art und Weise ist eine Hash Instanz a zu passieren, wenn b weggelassen?

versuchte ich

woot(x: 1) 
woot({x: 1}) 
h = {x: 1} 
woot(h) 

aber sie alle heben

ArgumentError: unknown keyword: x 

Der einzige Weg, um den Anruf zu machen, dass ich herausgefunden habe, ist

woot({x: 1}, **{}) 

Gibt es eine schönere Art und Weise?

+1

http://stackoverflow.com/questions/27821422/how-cani-i-collapse-double-splat-arguments-into-nothing :: ** TLDNR; ** es ist wahrscheinlich ein Bug in aktuellen Ruby impl. – mudasobwa

Antwort

1

Ihr erstes Argument ist optional, daher geht Ruby davon aus, dass der übergebene Hash für die benannten Argumente (*) gilt.

Ich glaube nicht, gibt es eine bessere Abhilfe, obwohl dies etwas kürzer ist (aber nicht unbedingt Reiniger):

woot({x: 1}, {}) 

Wenn ich Sie wäre, würde ich die Methode Signatur ändern, um die Mehrdeutigkeit aufzulösen.


(*): Na ja, nicht immer: woot({1=>3}) wird gerne den Hash auf das erste optionale Argument übergeben.

Noch seltsamer, im Fall von woot({1=> 5, :b => 4}) teilt Ruby das Wörterbuch auf und übergibt {1=>5} an den ersten optionalen Parameter.

Sieht aus wie es versucht, die genannten Parameter zuerst zu greifen (und wird sich über nicht vorhandene Namen beschweren), dann den Rest an die optionalen Parameter übergeben.

Aber ich würde gerne einige sprach Anwalt Erklärung sehen ...

+0

Wow, du hast Recht. Das ist noch seltsamer. Der Typ des Arguments ändert nicht nur die Art der Analyse, sondern auch den Typ der Schlüssel, die in argument enthalten sind. So viel zum Prinzip der geringsten Überraschung. – jedediah

+0

Es gibt mehr Überraschung ... :) Leider ist Ruby meistens "definiert" von was MRI tut, so dass es mir schwer ist, Absätze zu zitieren, vielleicht möchten Sie die MRI-Quelle nachschlagen ... –

0

Wenn Sie b ‚s Standardwert ändern nicht erwarten, jemals, wie wäre es explizit vorbei?

woot({x: 1}, b: nil) 

Natürlich, wenn b ‚s Standardwert tut Änderung eines Tages würden Sie noch in nil geben werden, so dass das Überschreiben der b Wert für diesen Anruf auf etwas anderes als seinen neuen Standardwert.