Ruby中的符号表设计与实现

时间:2012-01-26 01:20:36

标签: ruby symbol-tables symbol-table

我正在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的实例,唯一存在的对象是类级别1。

(假设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代码的任何评论。

由于

3 个答案:

答案 0 :(得分:1)

首选实例变量而不是类变量,如果没有其他原因,那么使用类变量的类对单元测试来说有点麻烦。

您可以使用实例变量,但仍然有一个符号表来统治它们。一种方法是将符号表分配给全局变量:

$symbol_table = SymbolTable.new

在某些语言中,使用全局变量的类很难测试。在Ruby中,它们并不是那么糟糕,因为鸭子类型允许您在执行测试对象之前将模拟对象分配给全局变量。

或者,您可以使用单例模式。 Ruby附带了一个库来简化:

require 'singleton'
class SymbolTable
  include Singleton
  ...
end

要检索SymbolTable的唯一实例,请根据需要创建它:

SymbolTable.instance

答案 1 :(得分:1)

使用实例变量。但不是(至少不仅仅是)出于测试处理的原因。而是因为

  • 每个解析过程都会产生它自己的符号表,所以你一次可能有多个
  • 仅在解析过程正在进行时才需要符号表
  • 类变量引入了进行同步以实现线程安全的必要性 - 即使每个解析过程都可以很好地与其自己的符号集完全相同

干杯

罗伯特

答案 2 :(得分:0)

快速澄清Robert和Wayne给出的几个答案,两者都提到类变量

原始问题并不建议使用类变量,而是要求使用类实例变量。 Hunter提出的第一个选择是使用类对象本身作为符号表的单个实例(状态存储在类实例变量中),而第二个选项使用更典型的类/实例框架,状态存储在符号的实例中表

Ruby的类变量与类实例变量不同,通常应该避免使用。