Ruby metaprogramming learning: "writing your first domain-specific language"

Source: Internet
Author: User
Tags glob

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.