zoukankan      html  css  js  c++  java
  • 读代码学RUBY之闭包

    #代码来源:http://rubyer.me/blog/917顺便学习 Ruby的4种闭包:blocks, Procs, lambdas 和 Methods。
    #first
    class Array
      def iterate!
        self.each_with_index do |n, i|
          self[i] = yield(n)
          yield(n)
        end
      end
    end
    
    array = [1, 2, 3, 4]
    
    array.iterate! do |x|
      x ** 2
    end
    
    puts array.inspect
    
    # => [1, 4, 9, 16]
    #second
    class Array
        def iterate!(&code)  #为iterate!传递一个参数&code,&表示这个参数是block。
            self.each_with_index do |n,i|
                self[i] = code.call(n)  #在iterate!中没有使用yield而是call。
            end
        end
    end
    
    array.iterate! do |n|
        n ** 2
    end
    
    puts array.inspect
    
    #third
    # ---PROC Procs 过程block与Proc惟一的不同是:block是不能保存的Proc,一次性的。
    square = Proc.new do |n|
        n ** 2
    end
    
    class Array
      def iterate!(code) #now these is not &code, not null, but code !!
          #注意:并没有在 iterate!的参数头部添加&,因为Proc只是一个普通类,不需要特殊处理。
        self.each_with_index do |n, i|
          self[i] = code.call(n)
        end
      end
    end
    
    array.iterate! square 
    
    puts array.inspect
    

      

    来源:http://rubyer.me/blog/917  

    首先,我们打开Array,并添加进iterate!方法。方法名以!结尾表示危险方法,引起注意。现在我们就可能像使用collect!一样使用iterate!

    与属性不同,在方法中不需要指定block的名字,而是使用yield来调用。yield会执行block中的代码。同时,注意我们是怎么把n(each_with_index当前处理的数字)传给yield的。传给yield的参数即对应了block中的参数(||中的部分)。现在n就能被block调用并在yield调用中返回n**2。
    整个调用如下:
    1、一个整数组成的数组调用iterate!
    2、当yield被调用时,把n(第一次为1,第二次为2,…)传给block
    3、block对n进行n**2。因为是最后一行,自动作为结果返回。
    4、yield得到block的结果,并把值重写到array里(这里用了self,在class和module的定义中,self代表这个class或这module对象,拓展阅读:http://fuliang.iteye.com/blog/272370
    5、数据中每个对象执行相同操作。

    def callbacks(procs)
      procs[:starting].call
    
      puts "Still going"
    
      procs[:finishing].call
    end
    
    callbacks(:starting => Proc.new { puts "Starting" },
              :finishing => Proc.new { puts "Finishing" })
    
    # => Starting
    # => Still going
    # => Finishing
    

     1、(:starting => Proc.new { puts "Starting" }, :finishing => Proc.new { puts "Finishing" } ) 这里定义了一个哈希表或者说字串符號 (Symbol) 。(一個 Symbol 物件皆為冒號開頭,例如 :foo 或 :foo_bar。它的作用就是代表一個名字,最大的作用就是當做 Hash 的鍵 (key),例如{ :foo => 1, :bar => 2 },在這裡我們只需要一個識別的名字,不需要使用字串物件。使用 Symbol 寫法更簡潔和獲得效能上的好處。)

       2、:starting => Proc.new { puts "Starting" } 键KEY为 :starting,键VALUE为 一个Procs 过程。

       3、procs[:starting].call 直接调用 储存在 procs[:starting] 中的 Procs 过程

     BTW:什么时候用blocks而不用Procs呢?我一般这样判断:
    1、Block:方法把一个对象拆分成很多片段,并且你希望你的用户可以与这些片段做一些交互。
    2、Block:希望自动运行多个语句,如数据库迁移(database migration)。
    3、Proc:希望多次复用一段代码。
    4、Proc:方法有一个或多个回调方法(callbacks)。


    未完,明天继续。

  • 相关阅读:
    LNOI2014LCA(树链剖分+离线操作+前缀和)
    CDQ分治与整体二分学习笔记
    BJWC2018上学路线
    NOIP2013火柴排队
    SHOI2008仙人掌图(tarjan+dp)
    作诗(分块)
    COGS314. [NOI2004] 郁闷的出纳员
    bzoj 1691: [Usaco2007 Dec]挑剔的美食家
    COGS1533.[HNOI2002]营业额统计
    bzoj1208: [HNOI2004]宠物收养所
  • 原文地址:https://www.cnblogs.com/likeyu/p/2364117.html
Copyright © 2011-2022 走看看