2009-11-06 7 views
19

Ich habe die neueste Ruby-Version ausgecheckt, um ein bisschen mit den letzten Änderungen zu spielen. Das erste, was ich zu tun versuchte, war ein Ruby-Lambda/Block/Proc aufzurufen, genau wie bei einem Python-Aufruf.Warum ist der Ruby 1.9 Lambda-Aufruf nicht möglich ohne den Punkt vor den Klammern?

a = lambda {|x| puts x} 
a.call(4) # works, and prints 4 
a[4] # works and prints 4 
a.(4) # same 
a(4) # undefined method 'a' for main:Object 

Warum ist der letzte Anruf nicht möglich? Wird es jemals sein?

Antwort

10

AFAIK ist, weil Ruby nicht die () Methode für ein Objekt definieren lässt. Der Grund dafür, dass Sie die ()-Methode nicht definieren können, liegt wahrscheinlich an der Tatsache, dass Klammern in Methodenaufrufen optional sind.

Und für was es wert ist, hier ist ein Hack Sie lambda ()http://github.com/coderrr/parenthesis_hacks/blob/master/lib/lambda.rb

+0

Kannst du bitte das Lambda-Skript etwas erklären? – Geo

+0

ok, wenn Sie versuchen, eine Methode mit dem Namen 'blah()' und 'method_missing' aufzurufen, wird geprüft, ob ein Lambda namens' blah' im entsprechenden Kontext definiert ist. Wenn solch ein Lambda definiert ist, dann ruft es einfach das Lambda mit der üblichen "blah.call" -Syntax auf, es gibt auch alle Parameter weiter, die gegeben wurden – horseyguy

+0

Ich denke, das ist ein genialer Hack. Vielen Dank. – Geo

6

Ruby ist im Grunde zu 100% objektorientiert, aber manchmal versucht es, diese Tatsache zu verbergen, um ... Bequemlichkeit? Vertrautheit?

Grundsätzlich sind Funktionen, die "auf der obersten Ebene" definiert sind, wirklich als Methoden auf einem globalen Objekt definiert. Um dies zu erreichen, wird ein Aufruf ohne einen Spezifizierer wirklich in das Aufrufen einer Methode mit diesem Namen auf dem globalen Objekt umgewandelt. Dieser Stil lässt die Dinge mehr nach Skript aussehen. Ruby versucht das mit deinem letzten Beispiel zu tun.

Die ersten beiden Beispiele analysieren fein, weil Ruby weiß, dass Sie versuchen, auf die Methoden des Proc-Objekts zuzugreifen - erinnern Sie sich sogar [] ist nur eine Methode, die Sie definieren können. Die mit dem expliziten Punkt funktioniert auch, weil der Punkt "diese Nachricht an dieses Objekt senden" bedeutet (in diesem Fall a).

Ich weiß, dass nichts "löst", aber ich hoffe, es hilft ein bisschen.

+1

Die Tatsache, dass Rubin ist OOP nicht erklären, mit aufrufen zu lassen, warum Sie nicht '() verwenden können,' ein Lambda aufzuzurufen. In vielen Sprachen können Sie eine '()' Methode für Ihre Objekte definieren. Die Frage ist, warum Ruby nicht erlaubt, einen '()' Operator zu definieren? – horseyguy

+1

(Gerade sah ich diesen Kommentar ...) Gute Frage. Vielleicht hat es etwas damit zu tun, wie Sie in bestimmten Situationen Klammern weglassen können; wäre seltsam, einen impliziten überladenen Operator-Aufruf zu haben. –