Как я могу обрабатывать функции как объекты в ruby?

#ruby

#ruby

Вопрос:

В моем проекте ruby я хочу создать класс диспетчера задач, который будет периодически выполнять итерации по массиву зарегистрированных функций. Мне нужно передать функции в качестве аргумента функции register, создать поток, и когда сработает таймер потока, ему нужно вызвать каждую функцию в массиве.

 class TaskMan

    @@func_array = Array.new

    def self.register_func amp;arg_func
        @@func_array.push arg_func
    end

    def self.run_server
        loop do
            @@func_array.each do |func|
                func.call
            end
            sleep 60 
        end
    end

end

class Callee

    def self.func_0
       puts "func_0 called."
    end

    def self.func_1
        puts "func_1 called."
    end

end

TaskMan.register_func Callee.func_0
TaskMan.register_func Callee.func_1

taskman_thread = Thread.new do
    TaskMan.run_server
end
taskman_thread.join
  

В принципе, это то, что я хочу сделать, но я не уверен, как использовать to_proc и call , чтобы вводить функции и вызывать их.

Другие решения также приветствуются, но я не хочу избегать обучения передаче функций в качестве аргументов, помещая их в массив и вызывая их.

Спасибо.

Комментарии:

1. В Ruby нет функций. Ваш вопрос неясен.

Ответ №1:

Используйте method метод, чтобы получить методы класса как вызываемые объекты (в данном случае Method экземпляры), а затем применить amp; к этим объектам:

 TaskMan.register_func amp;Callee.method(:func_0)
TaskMan.register_func amp;Callee.method(:func_1)
  

Теперь вы можете добавлять всевозможные вещи в func_array :

 TaskMan.register_func amp;SomeClass.method(:m)   # class method
TaskMan.register_func amp;some_object.method(:m) # an instance method
TaskMan.register_func amp;some_lambda            # a lambda function
TaskMan.register_func { puts "pancakes" }     # a block
# etc.
  

Ответ №2:

Вместо этого вы можете передать приемник и функцию, которую вы собираетесь вызвать, как показано ниже:

 class TaskMan

  @@func_array = Array.new

  def self.register_func(receiver, func)
    @@func_array.push([receiver, func])
  end

  def self.run_server
    loop do
      @@func_array.each do |(receiver, func)|
        receiver.method(func).call
      end
      sleep 60
    end
  end

end

class Callee

  def self.func_0
    puts "func_0 called."
  end

  def self.func_1
    puts "func_1 called."
  end

end

TaskMan.register_func Callee, :func_0
TaskMan.register_func Callee, :func_1

taskman_thread = Thread.new do
  TaskMan.run_server
end
taskman_thread.join
  

Ответ №3:

Допустим, у вас есть методы func_0 и func_1 . Чтобы вызвать их с помощью итерации массива, вы можете сделать это

 methods = [:func_0, :func_1]
methods.each do |m|
  send(m)
end
  

Комментарии:

1. вы не можете просто вызвать send(m) в примере OP, получатель функции не является self в его случае