• ruby


    def do_n_times(n){
      i = 1
      while( i<=n )
        yield i
      end
    }
    
    do_n_times( 3 ){ |x| puts "--->#{x}" }
    
    # --->1
    # --->2
    # --->3

     上面是使用关键字 yeild 来调用代码块,而下面的例子,在方法定义的时候定义了一个Proc 参数( 索引到传入的块),这个 Proc 参数需放在参数列表的最后,然后在方法里调用 call 方法,来调用Proc 块。

    注意这种使用方式和之前的方式,调用方法是一样的。

    片段2 : 

    def do_n_times(n , &p){
      i = 1
      while( i<=n )
        p.call(i)  # 调用 Proc.call 方法
      end
    }
    
    do_n_times( 3 ){ |x| puts "--->#{x}" } #注意这里的调用方式和之前的代码一样。
    
    # --->1
    # --->2
    # --->3

     下面的这种方式,你可以创建 Proc 对象,再传入到方法中. 这种方式在方法的定义中,参数 p 和普通的参数形式一样。

    片段3 : 

    def do_n_times(n , p){
      i = 1
      while( i<=n )
        p.call(i)
      end
    }
    p = Proc.new { |x| puts "--->#{x}" }
    do_n_times(3,p) # 这里直接传入Proc 对象 p
    
    # --->1
    # --->2
    # --->3

    在片段2中 &p 参数需放到参数列表的最后位置,由于 block 参数传入方法的特殊。而这里则没有这种限制。

    下面的代码片段,把两个数组的值加起来

    片段4 : 

    a, b = [0,1,2], [3,4]
    sum = a.inject(0) { |total, x| total+x }    # => 3 a数组的总和
    sum = b.inject(sum) { |total, x| total+x }  # => 10 a数组的总和加上 b数组的所有元素

    上面的代码,两次调用 inject 方法,都使用了相同的 block . 对于这样的情况,可以通过定义一个 Proc 对象来简化代码

    片段5 : 

    a, b = [0,1,2], [3,4]
    summation = Proc.new { |total,x| total+x }
    sum = a.inject(0, &summation)   # => 3 
    sum = b.inject(sum, &summation)  # => 10

    使用 &作为前缀的参数,需要放到参数列表的最后。其实任何方法调用都可以传递一个 block ,尽管方法并没有期望传进来 block, 尽管方法内部并没有调用 yeild。

    也就是说任何的方法调用都可以,传入一个 &参数,作为方法的最后一个参数。在一个方法调用中,& 符号通常出现在一个 Proc对象之前,实际上,它允许出现在

    任何对象( 有to_proc方法的对象), Method 类有这样一个方法,所以,Method对象能传递给 iterators ,像Proc 对象那样。

    在 Ruby1.9 中, Symbol 类定义了一个 to_proc 方法, 允许符号能在前面加 & 并传递给iterators . 当一个 symbol 通过这种方式传递,它被当成方法的名字,每个被迭代的对象都会调用该方法,如下

    片段6 : 

    words = ['and', 'but', 'bike'] 
    uppercase = words.map &:upcase #每个单词都调用upcase 方法
    upper = words.map { |w| w.upcase } #这个和上面是等价的
    
    # => ["AND", "BUT", "BIKE"]

    下面的代码对一个对象数组以对象的某个属性排序, 运用&Symbol 的方法

    class Person
      attr_accessor :name, :age
      def initialize(name,age)
        @name = name
        @age = age
      end
    end
    
    persons = [ Person.new('bbb',2),
                Person.new('aaa',3),
                Person.new('ccc',1),]
    
    by_attr = :name
    p persons.sort_by &by_attr
    
    by_attr = :age
    p persons.sort_by &by_attr

    # => [#<Person:0xb7b6ce54 @name="aaa", @age=3>, #<Person:0xb7b6ce04 @name="bbb", @age=2>, #<Person:0xb7b6cddc @name="ccc", @age=1>]
    # => [#<Person:0xb7b6cddc @name="ccc", @age=1>, #<Person:0xb7b6ce54 @name="bbb", @age=2>, #<Person:0xb7b6ce04 @name="aaa", @age=3>]

    上面的代码可以对persons 对象根据给定的属性排序,通过 &Symbol 这种方式,可以根据给定的symbol ( 实际应用中该值应该是传入值 ), 当然这里只是按照sort_by 默认的排序方向来排序,如需要换方向可以调用 reverse 方法。

  • 相关阅读:
    线性关系和相关系数
    CSS中的display:inlineblock
    SQL Server中常用的SQL语句
    Access SQL中Left Join、Right Join和Inner Join的使用
    PHP合并静态文件
    PHP中的include功能
    CSS背景图片居中的细节
    IIS Web服务扩展中添加ASP.NET4.0
    修改SQL server数据库中的逻辑文件名
    在SQL Server中,不使用“SQL 邮件”的情况下发送邮件
  • 原文地址:https://www.cnblogs.com/laoquans/p/3932788.html
Copyright © 2020-2023  润新知