• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 一個巢穴,二十種Ruby DSL(6)

    發表于:2013-02-28來源:圖靈社區作者:Martin Fowler點擊數: 標簽:
    item :secure_air_vent item :acid_bath, :uses = [acid(:type = :hcl, :grade = 5) , electricity(12)] item :camera, :uses = electricity(1) item :small_power_plant, :provides = electricity(11), :depends_on

      item :secure_air_vent

      item :acid_bath,

      :uses => [acid(:type => :hcl,

      :grade => 5) ,

      electricity(12)]

      item :camera,

      :uses => electricity(1)

      item :small_power_plant,

      :provides => electricity(11),

      :depends_on => :secure_air_vent

      使用這種方法有利有弊。對于像小型電廠這種簡單物件它非常合適。但對于如酸性溶液這種復雜物件,它卻不合適。酸性溶液依賴于兩種資源,所以需要把對acid和electricity的調用放在一個列表中。一旦把它們置于字面量映射中,代碼就變得很不直觀。

      接下來實現會變得更加復雜。對item方法的調用既需要名稱,也需要映射。在Ruby中會將其視作一個name參數后面跟著一個“名稱—值”對形式的多重參數。

      下載 lairs/builder4.rb

      def item name, *args

      newItem = Item.new name

      process_item_args(newItem, args) unless args.empty?

      @config.add_item newItem

      return self

      end

      process_item_args函數根據不同的鍵來切換處理每個閉包,要注意的是:args中的值可能是一個元素,也可能是一個列表。

      下載 lairs/builder4.rb

      def process_item_args anItem, args

      args[0].each_pair do |key, value|

      case key

      when :depends_on

      oneOrMany(value) {|i| anItem.add_dependency(@config[i])}

      when :uses

      oneOrMany(value) {|r| anItem.add_usage r}

      when :provides

      oneOrMany(value) {|i| anItem.add_provision i}

      end

      end

      end

      def oneOrMany(obj, &block)

      if obj.kind_of? Array

      obj.each(&block)

      else

      yield obj

      end

      end

      當你遇到這種情況——傳入的參數值既可能是一個單獨的元素,也可能是一個列表——時,始終把參數作為列表傳入通常會讓情況變得比較簡單。

      下載 lairs/rules21.rb

      item :secure_air_vent

      item :acid_bath,

      [:uses,

      acid(:type => :hcl, :grade => 5),

      electricity(12)]

      item :camera,

      [:uses, electricity(1)]

      item :small_power_plant

      [:provides, electricity(11)],

      [:depends_on, :secure_air_vent]

      上面代碼中item方法的參數是一個名稱和一個列表(而不是散列)。列表中的第一個元素是鍵,其后的元素是這個鍵對應的值(這就是Lisp程序員用列表模擬散列的方法)。這種方法減少了嵌套層次,并且更易處理。

      下載 lairs/builder21.rb

      def item name, *args

      newItem = Item.new name

      process_item_args(newItem, args) unless args.empty?

      @config.add_item newItem

      return self

      end

      def process_item_args anItem, args

      args.each do |e|

      case e.head

      when :depends_on

      e.tail.each {|i| anItem.add_dependency(@config[i])}

      when :uses

      e.tail.each {|r| anItem.add_usage r}

      when :provides

      e.tail.each {|i| anItem.add_provision i}

      end

      end

      end

      在這里需要注意的是,我們把列表當作了一個頭和尾的組合(而不是一系列元素)來處理。所以不要用只有兩個元素的列表來替換散列,因為那沒有任何價值。在這里我們用第一個元素為鍵,其他元素為值的列表替換散列,這樣我們就不需要在一個集合中嵌套另一個集合。

      頭和尾并非是Ruby的列表(叫做Array)默認具有的方法,但添加它們非常簡單。

      下載 lairs/builder21.rb

      class Array

      def tail

      self[1..-1]

      end

      alias head firsts

      end

      在結束字面量集合的討論之前,讓我們來看一看最后版本。下面就是以使用映射為主,列表為輔的整個配置代碼。

      下載 lairs/rules22.rb

      {:items => [

      {:id => :secure_air_vent},

      {:id => :acid_bath,

      :uses => [

      [:acid, {:type => :hcl, :grade => 5}],

      [:electricity, 12]]},

      {:id => :camera,

      :uses => [:electricity, 1]},

      {:id => :small_power_plant,

      :provides => [:electricity, 11],

      :depends_on => :secure_air_vent}

      ]}

      下面是只使用列表實現的版本,也叫Greenspun版本1。

      1 出自Philip Greenspun的“第十編程法則”:任何使用靜態類型檢查語言編寫的、足夠復雜的程序都包含一個特定、非正式定義、容易引入Bug且緩慢的動態檢查語言實現。——譯者注

      下載 lairs/rules6.rb

      [

      [:item, :secure_air_vent],

      [:item, :acid_bath,

      [:uses,

      [:acid,

      [:type, :hcl],

      [:grade, 5]],

      [:electricity, 12]]],

      [:item, :camera,

      [:uses, [:electricity, 1]]],

    原文轉自:http://www.ituring.com.cn/article/17818

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>