Pregunta

Estoy construyendo un analizador léxico en Ruby y estoy a punto de comenzar a recopilar y almacenar símbolos en la tabla de símbolos.Mi pregunta principal es sobre el diseño del símbolo y si debe ser una tabla estática (lo que significa que todos los datos se mantendrán en el nivel de clase) o si debe ser de una instancia a otra.

Opción 1:Estructura de datos a nivel de clase

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

Con este esquema, la clase SymbolTable tiene una especie de funcionalidad "estática", lo que significa que en realidad no creo una instancia de SymbolTable, el único objeto que existe es el de nivel de clase.

(Asumir que SymbolTableEntry es un objeto válido aunque no lo defina aquí)

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

Opcion 2:Estructura de datos a nivel de instancia

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

Con este esquema, realmente necesitaría crear una instancia de la clase SymbolTable para poder agregar valores a la tabla 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

Me encantaría escuchar todos los comentarios sobre qué diseño usaría o preferiría usar, así como cualquier comentario sobre el código Ruby en general.

Gracias

¿Fue útil?

Solución

Prefiera las variables de instancia a las variables de clase, aunque solo sea porque las clases que usan variables de clase son un poco más complicadas para las pruebas unitarias.

Puede usar variables de instancia y aún tener una tabla de símbolos para gobernarlos a todos.Una forma es asignando su tabla de símbolos a una variable global:

$symbol_table = SymbolTable.new

En algunos idiomas, las clases que utilizan variables globales son difíciles de probar.En Ruby, no son tan malos, ya que el tipeo pato te permite asignar objetos simulados a variables globales antes de ejecutar el objeto bajo prueba.

O puede utilizar el patrón singleton.Ruby viene con una biblioteca para facilitar esto:

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

Para recuperar la única instancia de SymbolTable, créela si es necesario:

SymbolTable.instance

Otros consejos

Utilice variables de instancia.Pero no (al menos no sólo) por razones de manejo de pruebas.Más bien porque

  • Cada proceso de análisis producirá su propia tabla de símbolos, por lo que es posible que tenga más de una a la vez.
  • la tabla de símbolos solo es necesaria mientras el proceso de análisis esté en marcha
  • las variables de clase introducen la necesidad de realizar sincronización para lograr la seguridad de los subprocesos, aunque cada proceso de análisis puede vivir perfectamente con su propio conjunto de símbolos.

Salud

roberto

Solo una rápida aclaración a un par de las respuestas dadas por Robert y Wayne, las cuales mencionan variables de clase.

La pregunta original no propone utilizar variables de clase en absoluto, pero sí pregunta sobre el uso variables de instancia de clase.La primera opción que presentó Hunter utilizó el objeto de clase en sí como la única instancia de la tabla de símbolos (con el estado almacenado en las variables de instancia de clase), mientras que la segunda opción usó un marco de clase/instancia más típico con el estado almacenado en una instancia del símbolo. mesa.

Las variables de clase de Ruby no son lo mismo que las variables de instancia de clase y, en general, deben evitarse.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top