2009-11-06 6 views
19

Ho controllato l'ultima versione di Ruby, per giocare un po 'con le ultime modifiche. La prima cosa che ho provato a fare è stato chiamare un lambda/block/proc Ruby come faresti con un Python callable.Perché la chiamata lambda Ruby 1.9 non è possibile senza il punto davanti alle parentesi?

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 

Perché non è l'ultima chiamata possibile? Sarà mai?

risposta

10

AFAIK perché ruby ​​non consente di definire il metodo () per un oggetto. Il motivo per cui non consente di definire il metodo () è probabilmente dovuto al fatto che le parentesi sono facoltative nelle chiamate di metodo.

E per quello che vale, ecco un trucco per far si richiama lambda utilizzando ()http://github.com/coderrr/parenthesis_hacks/blob/master/lib/lambda.rb

+0

puoi spiegare un po 'lo script di lambda? – Geo

+0

ok, quando provate a invocare un metodo chiamato 'blah()' e 'method_missing' viene attivato controlla se un lambda chiamato' blah' è definito nel contesto appropriato. Se tale lambda è definito, invoca semplicemente il lambda usando la consueta sintassi 'blah.call', passa anche qualsiasi parametro che è stato dato – horseyguy

+0

Penso che questo sia un tremendo trucco. Grazie. – Geo

6

Ruby è fondamentalmente orientato all'oggetto al 100%, ma a volte cerca di nascondere questo fatto per ... convenienza? Familiarità?

Fondamentalmente le funzioni definite "al livello superiore" sono in realtà definite come metodi su un oggetto globale. Per fare in modo che funzioni, una chiamata senza un identificatore viene realmente convertita a chiamare un metodo con quel nome su detto oggetto globale. Questo stile rende le cose più sceneggiate. Ruby sta cercando di farlo con il tuo ultimo esempio.

I primi due esempi vengono analizzati bene perché Ruby sa che stai tentando di accedere ai metodi dell'oggetto proc - ricorda che anche lo [] è solo un metodo che puoi definire. Quello con il punto esplicito funziona anche perché il punto significa "invia questo messaggio a questo oggetto" (in questo caso, a).

So che non "risolve" nulla, ma spero che aiuti un po '.

+1

Il fatto che Ruby è OOP non spiega il motivo per cui non è possibile utilizzare '()' per richiamare un lambda. Molte lingue ti permettono di definire un metodo '()' per i tuoi oggetti. La domanda è davvero perché il rubino non ti permette di definire un operatore '()'? – horseyguy

+1

(Appena visto questo commento ...) Buona domanda. Forse ha qualcosa a che fare con il modo in cui puoi omettere le parentesi in determinate situazioni; Sarebbe strano avere una chiamata operatore implicita in overload. –