2012-02-10 10 views
8

Sto scrivendo un semplice dsl in rubino. Qualche settimana fa mi sono imbattuto su alcuni post del blog, che mostrano come trasformare il codice come:Blocco DSL senza argomento in rubino

some_method argument do |book| 
    book.some_method_on_book 
    book.some_other_method_on_book :with => argument 
end 

in codice più pulito:

some_method argument do 
    some_method_on_book 
    some_other_method_on_book :with => argument 
end 

non riesco a ricordare come fare questo e io non sono sicuro di aspetti negativi, ma la sintassi più pulita è allettante. Qualcuno ha un indizio su questa trasformazione?

+0

Grazie per aver cambiato titolo! Ho avuto alcuni problemi con la formulazione. – dhuCerbin

risposta

9
def some_method argument, &blk 
    #... 
    book.instance_eval &blk 
    #... 
end 

AGGIORNAMENTO: Tuttavia, ciò omette il libro ma non consente di utilizzare l'argomento. Per utilizzarlo in modo trasparente devi trasportarlo in qualche modo. Suggerisco di farlo sul libro stesso:

class Book 
    attr_accessor :argument 
end 

def some_method argument, &blk 
    #... 
    book.argument = argument 
    book.instance_eval &blk 
    #... 
end 

some_method 'argument' do 
    some_method_on_book 
    some_other_method_on_book argument 
end 
+0

Grazie per l'aggiornamento. Ho bisogno di fare un po 'più di personalizzazione con la gestione degli argomenti, ma questo approccio comporta una buona sintassi. – dhuCerbin

7

Date un'occhiata a questo articolo http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation - v'è una panoramica del metodo (specificato nel contesto dei suoi lati negativi e possibile soluzione a loro), in più c'è' re diversi link utili per ulteriori letture.

Fondamentalmente, si tratta di utilizzare instance_eval per eseguire il blocco nel contesto desiderabile.

Parlando di aspetto negativo di questa tecnica:

Allora qual è il problema con esso? Bene, il problema è che i blocchi sono in genere chiusure. E ti aspetti che siano in realtà delle chiusure complete. E non è ovvio dal punto in cui si scrive il blocco che quel blocco potrebbe non essere una chiusura completa. Questo è ciò che accade quando si usa instance_eval altro - questo significa che il blocco è ancora una chiusura su tutte le variabili locali esterne al blocco, ma NON per le chiamate di metodo. Non so nemmeno se lo standard è stato modificato o meno.

Utilizzo di instance_eval modifica le regole per la lingua in modo che non sia evidente durante la lettura di un blocco. È necessario pensare ad un ulteriore passaggio per capire esattamente perché una chiamata al metodo che è possibile visualizzare in modo lessicale attorno al blocco non può essere chiamata dall'interno del blocco.

+0

Grazie, devo scavare di più sugli aspetti negativi. – dhuCerbin

0

Scopri la gemma docile. Si prende cura di tutti gli spigoli, rendendo questo molto facile per te.