Today I learned about the closure of Ruby. I mainly read the book "metapromgramming ruby:
Http://book.douban.com/subject/4086938/
In chapter 3, the closed boss at the end of the closure is a question: write your first domain-specific language.
event "the sky is falling" do @sky_height < 300endevent "It's getting closer" do @sky_height < @mountains_heightendsetup do puts "Setting up sky" @sky_height = 100endsetup do puts "Setting up mountains" @mountains_height = 200end
Write a program: redflag. RB. Run the above test file and get the following output:
Setting up skySetting up mountainsAlert: the sky is fallingSetting up skySetting up mountainsAlert: It's getting closer
The answer given by the author of the original book is as follows:
Def event (name, & Block) @ events [name] = block enddef setup (& Block) @ setups. push (Block) enddir. glob ('* event. RB '). each do | file | @ events ={}@ setups = [] Load file # Puts file @ events. each do | Name, event | Env = object. new () @ setups. each do | setup | Env. instance_eval & setup end puts "alert: # {name}" If Env. instance_eval & event end # Puts @ events. to_s # Puts @ setups. to_send # The two lines I added are used to test the scope of @ sky_height puts @ mountains_heigh
The previous steps are well understood. The key is the subsequent clean room:
env = Object.new() @setups.each do |setupa| env.instance_eval &setup end puts "Alert: #{name}" if env.instance_eval &event
This section aims to allow the & setup block and the & event block to run in the same object's env space to share the values of two variables: @ sky_height, @ mountains_height.
After I removed the clean room, I performed the following test In Proc. Call mode:
def event(name,&block) @events[name] = block enddef setup(&block) @setups.push(block)endDir.glob('*event.rb').each do |file| @events={} @setups=[] load file #puts file @events.each do |name,event| env = Object.new() @setups.each do |setup| setup.call end puts "Alert: #{name}" if event.call end #puts @events.to_s #puts @setups.to_send
# The two lines I added are used to test the scope of @ sky_height.
Puts @ sky_height
Puts @ mountains_heigh
It can also pass. However, we found that the two variables @ sky_height @ mountains_heigh have become a global variable-the proc-level variable. The variable value is typed at the end of the program.
In the Cleanroom method of the author, these two variables only exist in the context of env and are instance variables of this object. The two variables at the end of the program are nil.
This example demonstrates the functions of the clean room and flat scope.
At the end of this chapter, the author provides another more perfect method. Even the two global variables @ events @ setups are removed:
#---# Excerpted from "Metaprogramming Ruby",# published by The Pragmatic Bookshelf.# Copyrights apply to this code. It may not be used to create training material, # courses, books, articles, and the like. Contact us if you are in doubt.# We make no guarantees that this code is fit for any purpose. # Visit http://www.pragmaticprogrammer.com/titles/ppmetr for more book information.#---lambda { setups = [] events = {} Kernel.send :define_method, :event do |name, &block| events[name] = block end Kernel.send :define_method, :setup do |&block| setups << block end Kernel.send :define_method, :each_event do |&block| events.each_pair do |name, event| block.call name, event end end Kernel.send :define_method, :each_setup do |&block| setups.each do |setup| block.call setup end end}.callDir.glob('*events.rb').each do |file| load file each_event do |name, event| env = Object.new each_setup do |setup| env.instance_eval &setup end puts "ALERT: #{name}" if env.instance_eval &event endend
Appendix: AboutInstance_eval explanation:
Instance_eval can be an eval string or block in the context of an instance:
The instance_eval () method does the following three tasks:
A. Change self to the receiver of instance_eval.
B. Change the default definee TO THE eigenclass of the receiver. If no, create it.
C. Execute the block content.
Reference: http://book.douban.com/subject/4086938/annotation? Sort = rank & START = 20 blackanger book reviews