Ruby中的符号表设计与实现
-
14-11-2019 - |
题
我正在Ruby中构建一个词法分析器,即将开始在符号表中收集和存储符号。我关于符号设计的主要问题,以及它是否应该是静态表(意味着所有数据都将保存在类级别),或者它是否应该在实例到实例的基础上。
备选案文1:类级别的数据结构
require 'SymbolTableEntry.rb'
class SymbolTable
@sym_table = Array.new(500)
def initialize()
end
def SymbolTable.add(element, index)
@sym_table[index] = element if element.is_a? SymbolTableEntry
end
def SymbolTable.to_s
pp @sym_table
end
end
通过这种方案,SymbolTable类具有一种"静态"功能,这意味着我实际上并没有创建SymbolTable的实例,唯一存在的对象是类级别一。
(假设 SymbolTableEntry
是一个有效的对象,即使我没有在这里定义它)
前:
irb(main):002:0> require 'SymbolTable.rb'
=> true
irb(main):003:0> ste = SymbolTableEntry.new
=> #<SymbolTableEntry:0x7ef36884>
irb(main):004:0> SymbolTable.add(ste, 10)
=> #<SymbolTableEntry:0x7ef36884>
irb(main):005:0> SymbolTable.to_s
[nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
#<SymbolTableEntry:0x7ef36884>]
=> nil
备选案文2:实例级数据结构
require 'rubygems'
require 'backports'
require 'SymbolTableEntry.rb'
class SymbolTable
def initialize()
@sym_table = Array.new(10)
end
def add(element, index)
@sym_table[index] = element if element.is_a? SymbolTableEntry
end
def to_s
pp @sym_table
end
end
使用此方案,我实际上需要实例化SymbolTable类的实例,以便向符号表添加值。
irb(main):001:0> require 'SymbolTable.rb'
=> true
irb(main):002:0> st = SymbolTable.new
=> #<SymbolTable:0x7eeb6c9c @sym_table=[nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil]>
irb(main):003:0> ste=SymbolTableEntry.new
=> #<SymbolTableEntry:0x7eeb4d5c>
irb(main):004:0> st.add(ste,10)
=> #<SymbolTableEntry:0x7eeb4d5c>
irb(main):007:0> st.to_s
[nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
#<SymbolTableEntry:0x7eeb4d5c>]
=> nil
我很乐意听到您将使用或更喜欢使用的设计的任何和所有输入,以及对ruby代码的一般评论。
谢谢
解决方案
更喜欢实例变量而不是类变量,如果除了使用类变量的类对单元测试来说更痛苦的话。
您可以使用实例变量,并且仍然有一个符号表来规则它们。一种方法是将您的符号表分配给全局变量:
$symbol_table = SymbolTable.new
在某些语言中,使用全局变量的类很难测试。在Ruby中,它们并没有那么糟糕,因为duck typing允许您在执行被测对象之前将模拟对象分配给全局变量。
或者,您可以使用单例模式。Ruby有一个库来简化这件事:
require 'singleton'
class SymbolTable
include Singleton
...
end
要检索SymbolTable的唯一实例,请在需要时创建它:
SymbolTable.instance
其他提示
使用实例变量。但不是(至少不仅仅是)出于测试处理的原因。而是因为
- 每个解析过程都会产生它自己的符号表,因此您一次可能有多个符号表
- 只有在解析过程正在进行时,才需要符号表
- 类变量引入了进行同步以实现线程安全的必要性-即使每个解析过程都可以使用自己的一组符号完美地生活
干杯!
罗伯特
只是对罗伯特和韦恩给出的几个答案的快速澄清,这两个答案都提到 类变量.
原来的问题根本没有提出使用类变量,但确实询问了使用 类实例变量.Hunter提出的第一个选择使用类对象本身作为符号表的单个实例(状态存储在类实例变量中),而第二个选项使用更典型的类/实例框架,状态存储在符号表的
Ruby的类变量与类实例变量不是一回事,通常应该避免。