Разработка и внедрение таблицы символов в Ruby - PullRequest
2 голосов
/ 26 января 2012

Я строю лексический анализатор в 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 является допустимым объектом, хотя я не определяю его здесь)

Ex:

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

Мне бы очень хотелось услышать любые и все отзывы о том, какой дизайн вы бы использовали или предпочитаете использовать, а также любые комментарии к рубиновому коду в целом.

Спасибо

Ответы [ 3 ]

1 голос
/ 26 января 2012

Использовать переменные экземпляра.Но не (по крайней мере, не только) по причинам обработки теста.Скорее, потому что

  • каждый процесс разбора будет создавать свою собственную таблицу символов, поэтому вы можете иметь более одной таблицы одновременно
  • таблица символов необходима только до тех пор, пока процесс разбораВ процессе
  • переменные класса вводят необходимость выполнения синхронизации для достижения безопасности потока - даже если каждый процесс разбора может прекрасно жить со своим собственным набором символов

Cheers

роберт

1 голос
/ 26 января 2012

Предпочитайте переменные экземпляра над переменными класса, если только по той причине, что классы, использующие переменные класса, немного сложнее для модульного теста.

Вы можете использовать переменные экземпляра и при этом иметь одну таблицу символов дляправить ими всеми.Одним из способов является присвоение вашей таблицы символов глобальной переменной:

$symbol_table = SymbolTable.new

В некоторых языках классы, использующие глобальные переменные, сложно протестировать.В Ruby они не так уж и плохи, так как типизированная утка позволяет назначать фиктивные объекты глобальным переменным перед выполнением тестируемого объекта.

Или вы можете использовать шаблон синглтона.Ruby поставляется с библиотекой, облегчающей эту задачу:

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

Чтобы получить единственный экземпляр SymbolTable, создайте его при необходимости:

SymbolTable.instance
0 голосов
/ 27 января 2012

Просто краткое пояснение к нескольким ответам, данным Робертом и Уэйном, оба из которых упоминают переменные класса .

В первоначальном вопросе не предлагается использовать переменные класса впочти все спрашивают об использовании переменных экземпляра класса .Первый вариант, представленный Hunter, использовал сам объект класса в качестве единственного экземпляра таблицы символов (с состоянием, хранящимся в переменных экземпляра класса), в то время как второй вариант использовал более типичную структуру класса / экземпляра с состоянием, хранящимся в экземпляре Symbol.Таблица.

Переменные класса Ruby - это не то же самое, что переменные экземпляра класса, и их, как правило, следует избегать.

...