如何解决对块应用改进
假设我正在设计一种特定领域的语言。对于这个简化的例子,我们有变量、数字以及将事物加在一起的能力(变量或数字)
class Variable
attr_reader :name
def initialize(name)
@name = name
end
end
class Addition
attr_reader :lhs,:rhs
def initialize(lhs,rhs)
@lhs = lhs
@rhs = rhs
end
end
现在,如果我想表示表达式 x + 1
,我写 Addition.new(Variable.new('x'),1)
。
我们可以通过在 +
上提供 Variable
方法来使这更方便。
class Variable
def +(other)
Addition.new(self,other)
end
end
然后我们可以写Variable.new('x') + 1
。
但现在,假设我想要相反的:1 + x
。显然,我不想修补 Integer#+
,因为这会永久禁用普通的 Ruby 整数加法。我认为这将是一个很好的改进用例。
具体来说,我想定义一个方法 expr
,它接受一个块并在重新定义 +
以构造我的 DSL 实例的上下文中评估该块。也就是说,我想要类似的东西
module Context
refine Integer do
def +(other)
Addition.new(self,other)
end
end
end
def expr(&block)
Context.module_eval(&block)
end
因此,理想情况下,expr { 1 + Variable.new('x') }
将导致 DSL 表达式 Addition.new(1,Variable.new('x'))
。
然而,Ruby 的细化似乎非常善变,并且 module_eval
进入具有活动细化的作用域并不会像我希望的那样在块内激活该细化。有没有办法使用 module_eval
、instance_eval
等来激活特定 Ruby 块内的细化?
我意识到我可以将整数包装在 IntegerExpr
类中并在其上提供 +
。然而,这是 Ruby,元编程的极限是无限的,所以我很好奇它是否可以用普通的 Ruby Integer
实例来完成。我想定义一个方法 expr
这样,在
expr { 1 + Variable.new('x') }
块内的 +
是一个细化定义的 Integer#+
,即使该细化在 expr
的调用点处未激活。这可能吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。