2014-12-15 3 views
5

Während einige Leerzeichen Hinzufügen von Code besser lesbar (mit Code darüber Line-Up) zu machen, ich auf diese kam:Raum vor Stern bricht Syntax in Ruby Multiplikation Anweisung

class C 
    def x 
    42 
    end 
end 
m=C.new 

Jetzt wird diese geben „falsche Anzahl von Argumente ":

m.x *m.x 

Und das gibt "Syntaxfehler, unerwartete TSTAR, erwartet $" enden:

2/m.x *m.x 

Was genau passiert hier im Parser?

Ich habe mit Ruby 1.9.2 und 2.1.5 getestet.

Antwort

6

* wird sowohl für einen Operator (42 * 42) als auch für das Argument Entpacken (myfun *[42, 42]) verwendet.

Wenn Sie das tun:

m.x *m.x 
2/m.x *m.x 

Rubin interpretiert dies als Argument ausgepackt haben, anstatt die * Operator (dh Multiplikation.).

Falls Sie nicht mit ihm vertraut sind, Argument Auspacken (manchmal auch als „Klecks“ genannt, oder „splats“) bedeutet, dass Sie eine Funktion wie diese haben:

def myfun arg1, arg2; end 

Und es nennen wie dies:

myfun(*['Hello', 'World']) 

arg1 ist auf Hello und arg2 ist auf World.

Ich glaube, die Regeln zu bestimmen, welche zu benutzen ist:

  • Raum vor, aber nicht nach einem * -> Argument Auspacken
  • Beginn der Funktion Klammern -> Argument Auspacken
  • Alles else -> Multiplikation (oder besser der Operator *, da Ruby den Operator überlädt).

Gut Richtlinien sind:

  1. die "optional" Funktion Klammern verwenden, wenn Sie Argument beabsichtigen Auspacken;
  2. Verwenden Sie Leerzeichen vor und nach *, wenn Sie den Operator * beabsichtigen (Multiplikation).

Rubin warnt Sie eigentlich darüber, wenn Sie ruby -v laufen:

test.rb|11 warning| `*' interpreted as argument prefix          
test.rb|12 warning| `*' interpreted as argument prefix 
+0

War der Verdacht, dass es etwas damit zu tun hatte, aber die Fehlermeldungen waren nicht allzu hilfreich. +1 für Ruby -V. Sind die genauen Syntaxregeln dafür irgendwo dokumentiert? –

+1

@TrygveFlathen Da ist der Ruby [Ruby Draft Specification hier] (http://www.ipa.go.jp/osc/english/ruby/ruby_draft_specification_agreement.html) (klicken Sie auf "Ich stimme zu" am unteren Rand), versuchte ich zu sehen es hat aber keine Zeit, um Standard-Spezifikation-Sprache zu entwirren ;-) – Carpetsmoker

3

In einfacher Sprache:

Wenn Sie sagen,

m.x *m.x 

Es ruft intern m.x(*m.x) dh er hält *m.x als Splat-Argument zu m.x.

Da es eine x Methode definiert auf m, die jedes Argument (s) übernimmt, erhalten Sie die "falsche Anzahl von Argumenten" Fehler.

Wenn Sie anrufen

m.x * m.x 

Er hält * als Methode der x, die ein Objekt des Typs ‚Fixnum‘ und in Ruby nimmt, die * Methode, die ein Argument für ‚Fixnum‘ Klasse definiert. Also, es ist das gleiche wie das Rufen

m.x.*(m.x) 

und daher funktioniert es!

Ich hoffe, dass es Ihnen geholfen hat, das Problem zu verstehen, falls eine Klärung erforderlich ist, fühlen Sie sich frei zu kommentieren.