Как создать естественное распределение переменных - PullRequest
2 голосов
/ 28 июня 2011

Я работаю над довольно простым DSL и хотел бы объявлять и распределять переменные более естественно.

GlobalMemory.init {
  val1 5
  val2 "some string"
}

Это для простой виртуальной машины, которая запускает DSL. Это прекрасно работает для этого кода

class GlobalMemory
  include Singleton

  def self.init &blk
    GlobalMemory.instance.allocate &blk
  end

  def method_missing sym,*args, &blk
    @segments[sym]=args[0]
  end

  def allocate &blk
    self.instance_eval &blk
  end
end

Есть ли способ разрешить val1=5(and val1 = 5)? Когда я пытаюсь это сделать, method_missing не срабатывает, и сообщения об ошибках не появляются.

Ответы [ 2 ]

1 голос
/ 28 июня 2011

Я не думаю, что это можно сделать чисто как внутренний DSL

1 голос
/ 28 июня 2011

Будет работать как есть, если вы сделаете что-то вроде:

GlobalMemory.init {
    self.val3 = 'value'
}

В противном случае он неотличим от объявления локальной переменной. Я думаю, что лучший способ сделать это было бы иметь параметр блока и написать свой метод init следующим образом:

GlobalMemory.init { |g|
    g.val1 5
    g.val2 "some string"
    g.val3 = 'yeah'
}

Я немного возился с попыткой заставить решение var1 = работать с использованием #local_variables, но самое близкое, что я мог бы сделать, это:

class Foo
    def initialize(&bl)
        @data = {}
        b = yield self
        still_to_assign = eval('local_variables', b) - eval('local_variables', bl)
        still_to_assign.each { |v| r = eval(v,b); @data[v] = r }
    end
end

Foo.new {
    one = 1
    two = 2
    three = 3
    binding
}

Как вы можете видеть, это требует, чтобы вы возвращали объект привязки в конце вашего блока. У него также есть некоторые проблемы с переменными, которые уже были объявлены до блока. Может быть, кто-то может предложить лучший способ сделать это?

...