2013-12-23 5 views
3

Есть ли способ, которым я мог повернуть что-то вроде этого:Как я могу генерировать код из текста в Руби

SomeModule.some_method do 
    choos_one_from 1..10 
    then_multiply_it_by 2 
    then_multiply_it_by 5 
    then_divide_it_by :picked_number 
    then_subtract 7 
    did_you_get 3 
end 

в это:

(1..10).all? do |number| 
    ((number * 2 * 5)/number) - 7 == 3 
end 

?

Я попытался определить методы для всех возможных (select_one_from, then_multiply_it_by ...), которые принимают аргумент и что-то делают с ним, но так, когда вы получаете блок, он производит значения, но я действительно не знаю, как их объединить поэтому я могу получить второй кусок кода.

EDIT: У меня есть ощущение, что я должен сделать что-то вроде DSL

ответ

5

Вы хотели бы что-то вроде:

module Mathisizer 

    def when_i 
    Mathisizer::Builder.new 
    end 

    class Builder 
    attr_accessor :range, :choosen_number 

    def new 
     @operations = [] 
    end 

    def choose_one_from(range) 
     self.range = range 

     # Randomly determine the number from the range 
     # self.choosen_number = ... 

     self 
    end 

    def then_multiply_it_by(n) 
     @operations << MultiplicationOperation.new(n) 
     self 
    end 

    def then_add(n) 
     @operations << AdditionOperation.new(n) 
     self 
    end 

    def did_you_get?(n) 
     x = self.result 

     x == n 
    end 

    def result 
     x = choosen_number; 

     @operations.each do |operation| 
     x = operation.invoke(x) 
     end 

     x 
    end 
    end 

    class BaseOperation 
    def new(n) 
     @number = n 
    end 

    def invoke(n) 
     raise 'Base classes must implement invoke(n) -> number' 
    end 
    end 

    class MultiplicationOperation < BaseOperation 
    def invoke(x) 
     return @number * x 
    end 
    end 

    class AdditionOperation < BaseOperation 
    def invoke(x) 
     return @number + x 
    end 
    end 

end 

Где вы можете использовать его как:

Mathisizer.when_i 
    .choose_one_from(1..10) 
    .then_multiply_it_by(5) 
    .did_you_get?(3) 

В принципе, вы бы создали объект «строитель», который обеспечивает свободный API для создания математики ными объектами операции.

+0

Но, если я не знаю порядка «then_multiply_it», «then_devide_it_by». Как мне сделать правильную цепочку в Mathesizer.new? – user2128702

+0

@ user2128702 методы возвращают себя, поэтому порядок не имеет значения – bjhaid

+0

@GregBurghardt Итак, 'self' возвращает весь объект Mathesizer? – user2128702

Смежные вопросы