我正在尝试用Ruby编写内部DSL,并且在实现特定语法时遇到了麻烦。具体来说,如果我在一个类中有一个数组(或哈希),我想用括号访问和编辑它。例如:
class MyData
attr_accessor :things
def initialize
@things = ['right', 'right', 'wrong']
end
end
test = MyData.new
# This obviously won't work, but it's the syntax that I want.
test.things(2) = 'right'
我知道我可以通过以下方式读取具有此语法的元素:
class MyData
def things(index)
@things[index]
end
end
test = MyData.new
test.things(2) # => 'wrong'
但实际上更改元素完全是另一回事,因为Ruby不知道如何处理该赋值运算符。
我想要这种奇怪的语法的原因是因为我希望我可以使用这种语言轻松地将一些Fortran名单文件转换为友好的Ruby环境,但遗憾的是Fortran会使用括号对数组进行索引。
我担心的是,这只是我努力使Ruby违背其核心语法并且我需要实际编写解析器的情况之一。有什么想法吗?
答案 0 :(得分:1)
语法无效Ruby,你不能在Ruby中做到这一点。周期。
您有几种选择:
将语法更改为 有效的Ruby:
class MyData
attr_reader :things
private
attr_writer :things
def initialize
self.things = %w[right right wrong]
end
end
test = MyData.new
test.things[2] = 'right'
test.things
# => ['right', 'right', 'right']
使用支持该语法的语言,例如Scala:
class MyData {
var things = scala.collection.mutable.Seq("right", "right", "wrong")
}
val test = new MyData
test.things(2) = "right"
test.things
// => scala.collection.mutable.Seq[String] = ArrayBuffer(right, right, right)
创建一个外部DSL,即一个无效的Ruby。
事实上,看起来你已经 一个明确定义的外部DSL,特别是Fortran的一个子集。根据您是否可以控制这些名单文件,您甚至可以将语法进一步限制为可以通过一些Regexp
和一些文本修改来轻松解析的内容。
答案 1 :(得分:0)
调用操作符()
无法重载,因此无法完成您想要的技术操作。一种选择是预先处理你的DSL,用括号代替括号,然后再把它交给Ruby。
查看有关运营商重载的this other answer以获取更多信息。