InfoQ

新闻

Ruby 1.9中的#to_proc符号和(即将能用的)curried Procs

作者 Werner Schuster译者 贾晓楠 发布于 2008年2月28日 下午9时56分

社区
Ruby
主题
编程,
语言
标签
Ruby 1.9,
语言特性,
语言
Ruby 1.9除了具有像线程机制的改变或者纤程(Fibers)这些较大的新特性以外,还在标准库中增加了一些小而实用的功能。我们已经谈过了Object.tap方法,它带来了一种简便的方法来监视链式方法调用。

tap方法类似,to_proc已经在Ruby社区中出现一段时间了——Ruby 1.9预发布版本也具备了这个特性。Ruby 1.9简单地把它整合在Symbol类中,无须任何支持库就可以使用。

Reg Braithwaite简单地介绍了to_proc是怎样让 (1..100).inject(&:+) 这样的代码工作的:
& 操作符用来把Proc对象转化成块,或者把块转化成Proc对象。这此例中,它试图把符号 :+ 转换成一个块。此转换过程使用了Ruby内建的强制机制。这个机制会检查我们是否有一个Proc对象。如果没有,它就把#to_proc方法传递到参数中 来生成一个Proc。如果符号 :+ 有#to_proc方法,就调用它。在Ruby 1.9中,它就有一个#to_proc方法。此方法使用了第一个参数,然后返回一个Proc,并把 + 方法和其他参数传递给它。
由此可见,&:+ 实际上就是 { |x, y| x + y }
要完成这个动作,也可以采用下面的代码:
plus = :+.to_proc
puts plus.call(1,2) # prints '3'
由于Symbol类具有to_proc方法,由此所有的符号都可以这样使用:
to_s = :to_s.to_proc
to_s.call(42) # results in the string "42"
to_proc的实现很简单。Dave Thomas (PragDave) 演示了它是如何工作的
def to_proc
 proc { |obj, *args| obj.send(self, *args) }
end
当一个对象调用它时,就创建一个Proc,再把符号本身传递给对象。因此,比如当names.map(&:upcase)开始迭代names中的字符串时,它就调用里面这个块,把第一个name传递过去,并调用它的upcase方法。
这个特性也许可以产生非常简洁的代码,可是还有一个问题:它提高代码的可读性了吗?答案可能已经随着to_proc增加到Ruby 1.9标准库中而改变了,只是因为符号总是伴随着to_proc出现。

以前,方法的可用性依赖于代码或库是否开放符号并添加他们。而现在,理解这些代码需要用到#to_proc这个习惯称谓的知识,Ruby 1.9中已经正式加入了它,并且在文献中会越来越多的涉及到。

还剩下一个问题:
 (1..100).map(&:to_s) 
对比
 (1..100).map{|x| x.to_s } 
只不过省下5个字符(此例中)——额外带来的复杂性是否值得呢?

Ruby 1.9中还增加了一个涉及Procs的特性——尽管只存在于最近的修订版中:Proc#curry。最近在ruby-core中讨论了 Proc#curry 的作用
 它一点也不难,
 proc {|x, y, z| x + y + z }.curry
返回一个与下面代码等价的proc对象
 proc {|x| proc {|y| proc {|z| x + y + z } } }
这个方法的名字来源于Currying的概念,也就是:
[..] 是把带有多个参数的函数转化为带有单个参数的函数(其余的参数由curry来决定如何处理)
换 句话说:使用currying,一个带有x个参数的Proc,可以在调用时使用一个参数。当然,它显然不能返回代码的结果——还差几个参数才能运行代码 ——它返回一个带有(x - 1)个参数的新Proc。就这样一直迭代到最初的Proc有了足够的参数,代码才得以运行并返回结果。

例如,在同一个ruby核线程中,它可以这么用:
plus_five = proc { |x,y,z| x + y + z }.curry.call(2).call(3) 
plus_five[10] #=> 15
注意:plus_five是一个Proc——操作符[ ]被重载来调用它。

警告:Proc#curry最近才加入Ruby 1.9——要试一试的话,你必须使用最近的修订版。

查看原文:Ruby 1.9 with Symbol#to_proc and (soon) curried Procs

2 条回复

回复

我对于to_proc的解释 发表人 Ye Zheng 发表于 2008年2月29日 上午12时46分
哈哈哈哈 发表人 a x 发表于 2008年2月29日 上午1时15分
  1. 返回顶部

    我对于to_proc的解释

    2008年2月29日 上午12时46分 发表人 Ye Zheng

    写过一篇blog解释to_proc的用法。 一段Ruby代码的解释

  2. 返回顶部

    哈哈哈哈

    2008年2月29日 上午1时15分 发表人 a x

    还剩下一个问题: (1..100).map(&:to_s) 对比 (1..100).map{|x| x.to_s } 只不过省下5个字符(此例中)——额外带来的复杂性是否值得呢? ================ 我更喜欢(1..100).map{|x| x.to_s } 这种方式。“&:to_s”这个符号给我怪异无比,无法忍受的痛苦。呵呵

独家内容

世界顶尖运动队教练的成功秘诀

本文列出了来自于顶级教练Marc Lammers的9条原则,他是在打造世界最佳曲棍球队的过程中发现这些原则的,文章把这些原则映射到了软件开发实践之中。

探索JVM上的LISP

本文由Per Jacobsson所作,目标读者为有意了解Lisp的Java开发人员。文章探讨了当前可以运行于JVM上的不同Lisp方言,以明快简洁的方式介绍了Lisp程序设计工作机理和其独特之处,并在最后演示了Lisp代码同Java系统的整合过程。

Ruby/Rails: 不一样的'Web'应用

本文以一个实际应用的例子为引子,探讨Ruby/Rails在非传统web系统中应用,以及研究如何定制以Rails为基础的领域特定的MVC框架。

认识云计算

本视频对云计算进行了简要的介绍,主要包括了五部分内容:首先带大家认识“云”,然后对计算机的发展过程进行了阐述,接着介绍了业界现状和企业级/世界级计算的新布局,最后对云计算做了一下展望。

AtomServer:数据分发的发布动力

在这篇文章中,Bryon Jacob和Chris Berry介绍了AtomServer,一个基于Apache Abdera的完整Atom存储实现。在去年,作者一直致力于为其雇主——Homeaway——实现一个Atom存储,现在已开源了其Atom存储框架:AtomServer。

从卓越工程角度看微软中国开发团队的成长

开发团队的成长离不开优秀的人才,简捷有效的流程和高效率工具这三个卓越工程系统中的重要因素。本文作者从这三个因素分析了微软中国开发团队是如何“从优秀到卓越”的。

利用Ruby简化你的Java测试

本文是Productive Java with Ruby系列文章的第一篇,我将从单元测试这个话题开始,让Java的开发人员能够在实际工作中利用Ruby提高工作效率。

与赵进聊SaaS

InfoQ中文站有幸与阿里软件的首席架构师赵进在一起探讨了SaaS的相关话题,包括SOA和ASP与SaaS的异同、云计算、SaaS的前景、它的关键技术、技术瓶颈等等。