2016-07-13 5 views
1

Ruby n'a pas de fonctions de première classe; Bien qu'il ait procs et lambdas, ceux-ci nécessitent notoirement des frais généraux importants. (Python a premières fonctions de classe, apparemment sans les frais généraux.) Il me vint que les fonctions de première classe peuvent être simulés avec un peu plus de travail en utilisant des classes anonymes, comme suit:Ruby classes anonymes en tant que fonctions de première classe

f = Class.new { def self.f; puts 'hi'; end } 

def g(fun); fun; end 

g(f.f) 
# => "hi" 

Est-ce que quelqu'un sait mieux façon?

+1

Que voulez-vous dire par "mieux"? Qu'essayez-vous d'accomplir? Plus de vitesse, ou une fonctionnalité supplémentaire? –

+4

Lorsque vous appelez 'g (f.f)' dans le code ci-dessus, l'argument que vous passez à 'g' n'est pas une fonction. Vous appelez la méthode 'f.f' et passez le résultat, la chaîne' 'hi '' à 'g', qui retourne simplement son argument. –

+2

@Jordan En fait 'puts' renvoie' nil', donc 'g (f.f)' prend 'nil' comme argument. – Aetherus

Répondre

6

En fait, Ruby n'a pas de fonctions du tout, seulement des méthodes. Donc, si vous voulez passer une méthode à une autre méthode, vous pouvez

def g(f) 
    f.call 
end 

g('123'.method(:to_i)) 

Ceci est moins concis que Python, mais il est le prix que Ruby doit payer pour la possibilité d'omettre les parenthèses dans les appels de méthode. Je pense que l'omission des parenthèses est l'une des choses qui font briller Ruby, parce que cela rend beaucoup plus facile la mise en place de DSL en Ruby pur.

+0

Je ne comprends pas votre remarque sur la mise en œuvre des DSL, mais cela semble intéressant - quelque chose que je vais devoir examiner. Il est peut-être intéressant de noter que si la méthode est d'abord convertie en proc, la proc peut être passée à 'g':' proc = '123'.method (: to_i) .to_proc # => # ; g (proc) # => 123'. –

1

Ruby a proc s et lambda s (les deux instances de la classe Proc) et Method s, qui toutes les fonctions de premier ordre approximatives. Les Lambdas sont les plus proches d'une vraie fonction de première classe: ils vérifient le nombre d'arguments lorsqu'ils sont appelés et créent un nouveau contexte d'appel tel que return revient juste de lambda. En revanche, les procs sont juste des blocs de code réifiés; ils ne vérifient pas leur nombre d'arguments, et un return provoque le retour de la méthode englobante, pas seulement le proc.

Les objets de méthode vous permettent de stocker une méthode non appelée dans une variable, complétée par un invocant implicite. Il n'y a pas de syntaxe pour créer une méthode anonyme, mais vous avez dit des fonctions de première classe, pas anonymes. A part l'invocant, ce sont essentiellement des lambdas dont le corps est celui de la méthode référencée. Je ne suis pas sûr que ce que vous obtenez une classe anonyme est mieux que les solutions ci-dessus, mais il est certainement plus loin d'une véritable fonction de première classe. Cela ressemble plus à la façon dont nous devions les rapprocher en Java avant que les fermetures aient été ajoutées à la langue.