Domanda

Sto costruendo un analizzatore lessicale in Ruby e sto per iniziare a raccogliere e archiviare simboli nella tabella dei simboli. La mia principale domanda sulla progettazione del simbolo e sul fatto che dovrebbe essere la tabella statica (il che significa che tutti i dati verranno conservati a livello di classe) o se dovrebbe essere su un'istanza a istanza.

Opzione 1: Struttura dati a livello di classe

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 questo schema, la classe Symboltable ha una sorta di funzionalità "statica", il che significa che in realtà non creo un'istanza di un simbolo, l'unico oggetto che esiste è il livello di classe.

(supponi che SymbolTableEntry sia un oggetto valido anche se non lo definisco qui)

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
.

Opzione 2: Struttura dei dati del livello di istanza

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 questo schema avrei effettivamente bisogno di istanziare un'istanza della classe Symboltable per aggiungere valori alla tabella dei simboli.

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
.

Mi piacerebbe sentire qualsiasi e tutti gli input su quale design si useresti o preferiresti utilizzare, pure eventuali commenti sul codice rubino in generale.

Grazie

È stato utile?

Soluzione

Preferisci variabili di istanza oltre le variabili di classe, se non per nessun altro motivo rispetto a quelle classi utilizzando le variabili di classe sono un po 'più di un dolore al test unitario.

È possibile utilizzare le variabili di istanza e avere ancora una tabella dei simboli per regolarli tutti.Un modo è assegnando la tabella dei simboli a una variabile globale:

$symbol_table = SymbolTable.new
.

In alcune lingue, le classi che utilizzano variabili globali sono difficili da testare.In Ruby, non sono così cattivi, poiché Duck Witing ti consente di assegnare oggetti finti alle variabili globali prima di eseguire l'oggetto sotto test.

Oppure, è possibile utilizzare il modello Singleton.Ruby viene fornito con una biblioteca per renderlo facile:

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

Per recuperare l'istanza di unica e solo di simboli, lo creò se necessario:

SymbolTable.instance
.

Altri suggerimenti

Utilizzare le variabili di istanza.Ma non (almeno non solo) per motivi di gestione dei test.Piuttosto perché

    .
  • Ogni processo Parse produrrà la sua tabella dei simboli propri, quindi potresti averne più di uno in un momento
  • La tabella dei simboli è necessaria solo finché il processo Parse è in corso
  • Le variabili di classe introducono la necessità di fare la sincronizzazione per ottenere la sicurezza del filo - anche se ogni processo di analisi può vivere perfettamente bene con il proprio set di simboli

    Cheers

    Robert

Solo un rapido chiarimento in un paio di risposte fornite da Robert e Wayne, entrambe di menzione Variabili di classe .

La domanda originale non propone di utilizzare le variabili di classe, ma chiede informazioni sull'utilizzo delle variabili di istanza di classe .Il cacciatore di prima scelta ha presentato l'oggetto della classe stesso come la singola istanza della tabella dei simboli (con stato memorizzato nelle variabili di istanza di classe) mentre la seconda opzione utilizzava un quadro di classe / istanza più tipico con lo stato memorizzato in un'istanza del simboloTabella.

Le variabili di classe di Ruby non sono la stessa cosa delle variabili di istanza di classe e dovrebbero generalmente essere evitate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top