Tabela de símbolos de Design e Implementação em Ruby
-
14-11-2019 - |
Pergunta
Eu estou construindo um analisador léxico em Ruby e estou prestes a começar a reunir e armazenar símbolos na tabela de símbolos.A minha principal questão sobre o desenho do símbolo e como se deve ser estático tabela (o que significa que todos os dados serão mantidos no nível de classe) ou se deve ser uma instância para a instância de base.
Opção 1:Classe nível da estrutura de dados
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
Com este esquema, a classe SymbolTable tem uma espécie de 'estático', funcionalidade, o que significa que eu realmente não criar uma instância de um SymbolTable, o único objeto que existe é a classe de nível.
(Suponha que SymbolTableEntry
é um objeto válido, mesmo que eu não definir aqui)
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
Opção 2:Exemplo de nível de estrutura de dados
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
Com esse esquema que eu seria realmente necessário criar uma instância da classe SymbolTable para adicionar valores para a tabela de símbolos.
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
Eu gostaria de ouvir qualquer e todas as entradas em que projeto você gostaria de usar ou se preferir utilizar, bem como quaisquer comentários sobre o código de ruby em geral.
Obrigado
Solução
Preferem variáveis de instância sobre variáveis de classe, se por nenhuma outra razão do que classes usando variáveis de classe são um pouco mais de dor para o teste de unidade.
Você pode usar variáveis de instância e de ainda ter uma tabela de símbolos para a todos governar.Uma maneira é através da atribuição de sua tabela de símbolos para uma variável global:
$symbol_table = SymbolTable.new
Em alguns idiomas, classes que usam variáveis globais são difíceis de testar.Em Ruby, eles não são tão ruim, uma vez que duck typing permite atribuir objetos mock para variáveis globais antes de executar o objeto sob teste.
Ou, você pode usar o padrão singleton.Ruby vem com uma biblioteca para fazer isso fácil:
require 'singleton'
class SymbolTable
include Singleton
...
end
Para recuperar a uma instância do SymbolTable, criou-o, se necessário:
SymbolTable.instance
Outras dicas
Use variáveis de instância.Mas não (pelo menos não apenas) por razões de teste de manipulação.Sim porque
- cada analisar o processo de produzir a sua própria tabela de símbolos, de modo que você pode ter mais de um de cada vez
- a tabela de símbolos é apenas necessário, desde como funciona o processo de análise é sob a forma
- variáveis de classe introduzir a necessidade de fazer a sincronização para alcançar o thread de segurança - mesmo que analisar cada processo pode viver perfeitamente bem com o seu próprio conjunto de símbolos
Cheers
robert
Basta uma rápida clarificação de algumas das respostas dadas por Robert e Wayne, tanto que menciona variáveis de classe.
A pergunta original não propõem usar variáveis de classe em tudo, mas não perguntar sobre o uso de classe de variáveis de instância.A primeira escolha Hunter apresentou usada a classe de objeto em si como a única instância da tabela de símbolos (com o estado armazenado na classe de variáveis de instância), enquanto a segunda opção mais típico de classe/instância do framework com o estado armazenado em uma instância da tabela de símbolos.
Ruby variáveis de classe não são a mesma coisa que a classe de variáveis de instância e deve ser evitada.