2017-01-22 3 views
3

Я хотел бы определить метод [] для класса моего собственного создания, чтобы взять блок. Я сделал это следующим образом.Ruby Bracket Method with Block

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

Я могу вызвать это следующим образом.

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

Однако, я хотел бы иметь возможность это сделать.

A[3] { |x| puts x } 

К сожалению, похоже, что возникает синтаксическая ошибка. Есть ли синтаксис блока для метода скобки, или я придерживаюсь первых двух способов его вызова? На самом деле, в более общем плане, какие имена Ruby-метода позволят блокировать в их вызове, поскольку, похоже, может быть ограничение на то, когда это разрешено?

+0

Я не думаю, что есть способ. 'A.send ('[]', 3) {| x | puts x} 'является альтернативой, но не настолько фантазией. – mrlew

ответ

1

Существует мало что можно сделать против синтаксической ошибки, поэтому вам придется изменить синтаксис.

Если вы принимаете:

  • определить (т.е. загрязняет) прописной метод внутри Kernel (аналог Kernel#Array)
  • использовать скобки вместо скобки

Вы могли бы написать:

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 

Это работает таким образом :

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

Это не чистый, но это, вероятно, ближе вы можете быть A[3] { |x| puts x }.

+0

Downvoter: конструктивная критика приветствуется. –

+0

Мне понравилось решение, не знал о модуле ядра +1 – mrlew

3

Блоки работают только с обычными вызовами метода.

В Ruby есть много операторов, список всех из них здесь будет исчерпывающим, их более двух десятков. Даже `a` и !a и -a являются вызовами метода в Ruby. И, очевидно, существуют ограничения для всех этих операторов, например, + должен принимать один параметр, но не более, и так далее.

Забавный факт, loop - вызов метода.