Ruby中的Proc类及Proc的类方法Proc.new的使用解析

 更新时间:2016年05月27日 15:35:40   作者:imxieke  
用Proc类可以用Proc.new来创建一个Proc类,进而来操作块,这里我们就来进行Ruby中的Proc类及Proc的类方法Proc.new的使用解析.

Proc是对块及其context(局部变量的作用域以及栈框架)进行对象化处理之后得到的过程对象。您可以像使用无名函数那样来使用Proc,但它不会导入局部变量的作用域(可以把动态局部变量用作Proc局部变量)。

在下例中,正因为Proc一直保持着局部变量的作用域,所以才能调用var变量。

var = 1
$foo = Proc.new { var }
var = 2

def foo
 $foo.call
end

p foo    # => 2

从生成Proc的方法中返回以后,若Proc中出现return或retry的话,会引发LocalJumpError异常。

def foo
 proc { return }
end

foo.call
# => in `call': return from proc-closure (LocalJumpError)

def foo
 proc { retry }
end

foo.call
# => in `call': retry from proc-closure (LocalJumpError)

若在Proc前面加上"&"并将其传给一个带块的方法时,其运作情形类似于调用块。但从严格意义上讲,其间还存在以下不同。

# 没问题
(1..5).each { break }

# 在ruby 1.6.7, 1.8中没问题。在1.6.8中则发生异常
proc = Proc.new { break }
(1..5).each(&proc)

# 在ruby 1.6 中是 LocalJumpError
# 在ruby 1.8 中,再次运行each
proc = Proc.new { retry }
(1..5).each(&proc)
#=> retry from proc-closure (LocalJumpError)

这正是Proc对象用作调用块时的限制。

Proc.new
Proc.new { ... }

对块及其context进行对象化处理之后返回结果。

若没有给出块的话,就会把调用该方法的方法所带的块转换为Proc对象并将其返回。

def foo
  pr = Proc.new
  pr.call(1,2,3)
end
foo {|args| p args }
# => [1, 2, 3]

Proc.new方法深入
Proc.new对块及其context进行对象化处理之后返回结果。

若没有给出块的话,就会把调用该方法的方法所带的块转换为Proc对象并将其返回。

def foo
  pr = Proc.new
  pr.call(1,2,3)
end
foo {|args| p args }
# => [1, 2, 3]
这与下例相同
def foo
 yield(1,2,3)
end
foo {|args| p args }
# => [1, 2, 3]

若主调方法并没有带块时,则引发ArgumentError异常。

def foo
 Proc.new
end
foo
# => -:2:in `new': tried to create Proc object without a block (ArgumentError)
     from -:2:in `foo'
     from -:4

在使用Proc.new时,若定义了Proc#initialize方法的话,就在对象初始化时调用该方法。除此以外,它和proc是相同的。

利用 Proc.new 方法,或者对 proc 方法指定块,都可以创建代表块的 Proc 对象。

通过调用 Proc#call 方法执行块。调用 Proc#call 方法时的参数会作为块变量,块中最后一个表达式的值则为 Proc#call 的返回值。Proc#call 还有一个名称叫 Proc#[]。

# 判断西历的年是否为闰年的处理
leap = Proc.new do |year|
 year % 4 == 0 && year % 100 != 0 || year % 400 ==0
end
 
p leap.call(2000)  #=> true
p leap[2013]     #=> false
p leap[2016]     #=> true

将块变量设置为 |* 数组 | 的形式后,就可以像方法参数一样,以数组的形式接收可变数量的参数。

double = Proc.new do |*args|
 args.map{|i| i * 2 }  # 所有元素乘两倍
end
 
p double.call(1, 2, 3)  #=> [2, 3, 4]
p double[2, 3, 4]     #=> [4, 6, 8]

除此以外,定义普通方法时可使用的参数形式,如默认参数、关键字参数等,几乎都可以被用于块变量的定义,并被指定给 Proc#call 方法。

相关文章

  • 解析proxy代理模式在Ruby设计模式开发中的运用

    解析proxy代理模式在Ruby设计模式开发中的运用

    这篇文章主要介绍了proxy代理模式在Ruby设计模式开发中的运用,通过代理模式以客户透明的形式可以动态地为目标对象加以行为控制,需要的朋友可以参考下
    2016-04-04
  • 浅析Ruby中的DATA对象

    浅析Ruby中的DATA对象

    这篇文章主要介绍了Ruby中的DATA对象,包括对DATA.read方法的讲解等,需要的朋友可以参考下
    2015-05-05
  • Ruby Dir 类和常用方法

    Ruby Dir 类和常用方法

    Ruby编程语言中的Dir类包括多种用于目录处理的方法,本文详细介绍了如何使用Dir.chdir更改工作目录、Dir.children列出目录内容、Dir.delete删除空目录等常用方法,通过示例,读者可以学习如何在Ruby程序中有效地浏览和操作文件系统的目录结构
    2024-09-09
  • Ruby简明教程之方法(Method)介绍

    Ruby简明教程之方法(Method)介绍

    这篇文章主要介绍了Ruby简明教程之方法(Method)介绍,ruby的方法分为实例方法、类方法、函数方法等,本文分别做了讲解,需要的朋友可以参考下
    2014-06-06
  • ruby实现网页图片抓取

    ruby实现网页图片抓取

    本文给大家分享的是个人使用ruby编写的抓取网页图片的代码,十分的简单实用,有需要的小伙伴可以参考下。
    2015-06-06
  • ruby中执行周期性任务(定时任务)的3种方法

    ruby中执行周期性任务(定时任务)的3种方法

    这篇文章主要介绍了ruby中执行周期性任务(定时任务)的3种方法,本文通过使用whenever、sidetiq、clockwork等gem实现,需要的朋友可以参考下
    2014-10-10
  • 详解Ruby设计模式编程中对单例模式的运用

    详解Ruby设计模式编程中对单例模式的运用

    这篇文章主要介绍了Ruby设计模式编程中对单例模式的运用,讲到了包括对Singleton模块的使用,需要的朋友可以参考下
    2016-03-03
  • 在Ruby on Rails中使用AJAX的教程

    在Ruby on Rails中使用AJAX的教程

    这篇文章主要介绍了在Ruby on Rails中使用AJAX的教程,文章来自于IBM官方网站技术文档,需要的朋友可以参考下
    2015-04-04
  • 使用Ruby re模块创建复杂的正则表达式

    使用Ruby re模块创建复杂的正则表达式

    复杂的正则表达式很难构建,甚至很难阅读。Ruby的Re模块可以帮助你利用简单的表达式构建复杂的正则表达式
    2014-03-03
  • Ruby教程之注释、变量声明以及数组操作

    Ruby教程之注释、变量声明以及数组操作

    这篇文章主要介绍了Ruby教程之注释、变量声明以及数组操作,本文是Ruby语言的一篇入门教程,需要的朋友可以参考下
    2014-09-09

最新评论