2017-01-22 1 views
3

Je voudrais définir la méthode [] sur une classe de ma propre création pour prendre un bloc. Je l'ai fait comme suit.Méthode Ruby Bracket avec le bloc

class A 
    def self.[](*args, &block) 
    puts "I am calling #{block} on #{args}." 
    block.(*args) 
    end 
end 

Je peux invoquer ceci comme suit.

# Explicit method invocation 
A.[](1) { |x| puts x } 
# With a procedure argument 
arg = proc { |x| puts x } 
A[2, &arg] 

Cependant, ce que je voudrais pouvoir faire est ceci.

A[3] { |x| puts x } 

Ce qui semble malheureusement produire une erreur de syntaxe. Existe-t-il une syntaxe de bloc pour la méthode bracket, ou suis-je bloqué avec les deux premières manières de l'invoquer? En fait, plus généralement, quels noms de méthodes Ruby autoriseront les blocs dans leur invocation, car il semblerait qu'il y ait une limitation sur quand cela est autorisé?

+0

Je ne pense pas qu'il y ait un moyen. 'A.send ('[]', 3) {| x | met x} 'est une alternative, mais pas si chic. – mrlew

Répondre

1

Vous ne pouvez pas faire grand-chose contre une erreur de syntaxe, vous devrez donc modifier la syntaxe.

Si vous acceptez:

  • pour définir (par exemple pollute) une méthode en majuscules à l'intérieur Kernel (similaire à Kernel#Array)
  • à utiliser parens au lieu des crochets

Vous pouvez écrire:

class A 
    def self.call_block_with_args(*args, &block) 
    puts "I am calling #{block} on #{args}." 
    block.call(*args) 
    end 
end 

module Kernel 
    def A(*args, &block) 
    A.call_block_with_args(*args, &block) 
    end 
end 

Cela fonctionne de cette façon :

A(3) { |x| puts x } 
#=> 
# I am calling #<Proc:[email protected]_brackets.rb:14> on [3]. 
# 3 

Ce n'est pas propre, mais il est probablement le plus proche, vous pouvez être à A[3] { |x| puts x }.

+0

Downvoter: la critique constructive est la bienvenue. –

+0

J'ai aimé la solution, je ne savais pas sur le module du noyau +1 – mrlew

3

Les blocs ne fonctionnent qu'avec les appels de méthode normaux.

Ruby a beaucoup d'opérateurs, énumérant tous ici serait exhaustive, il y a plus de deux douzaines. Même `a` et !a et -a sont des appels de méthode dans Ruby. Et évidemment il y a des limitations à tous ces opérateurs, par exemple + doit prendre un paramètre mais pas plus, et cetera.

Fun fait, loop est également un appel de méthode.