如何创建自然变量分配

发布于 2024-11-17 05:28:11 字数 543 浏览 3 评论 0原文

我正在开发一个相当简单的 DSL,并且希望更自然地声明和分配变量。

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

这是针对运行 DSL 的简单 VM。这对于这段代码来说效果很好

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 不会触发,也不会出现错误消息。

I am working on a fairly simple DSL and would like to be declare and allocate variables more naturally.

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

This is for a simple VM that runs the DSL. This works just fine for this code

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

Is there a way to allow val1=5(and val1 = 5)? When I try that, method_missing doesn't trigger and no error messages occur.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春花秋月 2024-11-24 05:28:11

如果您执行以下操作,它将按原样工作:

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

否则,它与局部变量声明无法区分。我想更好的方法是有一个块参数并像这样编写你的 init 方法:

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

我尝试使用 #local_variables 使 var1= 解决方案工作,但我能得到的最接近的是:

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
}

正如您所看到的,它要求您在块的末尾返回一个绑定对象。对于在块之前已经声明的变量,它也存在一些问题。也许有人可以建议更好的方法来做到这一点?

It will work as-is if you do something like:

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

Otherwise it's indistinguishable from a local variable declaration. I guess the nicer way to do it would be to have a block parameter and write your init method like this:

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

I messed around a bit with trying to get the var1= solution working using #local_variables, but the closest I could come is this:

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
}

As you can see, it requires you to return a binding object at the end of your block. It also has some issues with variables that have already been declared prior to the block. Maybe someone can suggest a better way to do this?

酷遇一生 2024-11-24 05:28:11

我认为作为内部 DSL 不可能干净地做到这一点

I don't think it is possible to do this cleanly as an internal DSL

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文