Domanda

Voglio scrivere un semplice Ruby DSL per tradurre alcune frasi ed espressioni in un'altra lingua.Un esempio di base sarebbe:

some_function {
    t + 2
}

Qui, t non è un rubino variabile e quindi il blocco non può (e non deve!) essere valutati da Ruby.Quindi la mia scommessa migliore sarebbe quella di utilizzare l'analisi di uscita (o AST) per fare la traduzione da me.Per farlo, è possibile utilizzare ParseTree e ruby2ruby.Tuttavia, ho altri costrutti che vorrei utilizzare, per esempio:

1.upto(10) {|x|
    some_function {
        t + x
    }
}

Qui, ho una variabile locale e ho bisogno di ottenere il suo valore, al fine di fare la mia traduzione.Tuttavia, la funzione che esegue il blocco di valutazione, non ho accesso alle variabili locali di blocco di chiamata.Se fosse una variabile globale ($x), non ho potuto verificare se il suo nome è già presente nel global_variables array e nel peggiore dei casi l'uso di eval, ma come avrei potuto farlo per una variabile locale, se possibile a tutti?

Aggiornamento:

Giusto per chiarire le cose.Come ho detto inizialmente, sto utilizzando ruby2ruby (e quindi ParseTree) per ottenere l'AST (utilizzando to_sexp) corrispondente al blocco.Ma quando si utilizza una variabile locale all'interno del mio blocco, mi incontro con il seguente:

[:dvar, :x]

E così, avrei bisogno di ottenere il valore di una variabile dal nome come stringa/simbolo.E non posso usare method_missing o instance_eval, perché ho voglia di tradurre tutto espressione di un'altra lingua o di sintassi (come un RPN).

Un'altra soluzione non si basa su ParseTree sarebbe il benvenuto tuttavia, dal momento che a quanto pare non è pienamente supportato con Ruby 1.9.

È stato utile?

Soluzione

Per ottenere i valori delle variabili, utilizzare il proc dell'associazione:

def some_function(&block)
  b = block.binding
  p [b.eval("t"), b.eval("x")]
end

t = 1
1.upto(10) {|x|
  some_function {
    t + x
  }
}

Altri suggerimenti

Qui, t non è un rubino variabile e quindi il blocco non può (e non deve!) essere valutati da Ruby.

Motivo per i "non valutato" restrizione?Sembra method_missing vorresti gestire in modo elegante la valutazione del "mancanti" t variabile, ma Ruby sarebbe automaticamente risolvere l' x variabile.

È possibile utilizzare instance_eval contro un oggetto con t.

class Context
  attr_accessor :t

  def initialize(_t)
    @t = _t
  end
end

def some_function(&block)
  puts Context.new(1).instance_eval(&block)
end

1.upto(10) {|x|
  some_function {
    t + x
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top