写点什么

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

2008 年 2 月 28 日

Ruby 1.9除了具有像线程机制的改变或者纤程(Fibers)这些较大的新特性以外,还在标准库中增加了一些小而实用的功能。我们已经谈过了 Object.tap方法,它带来了一种简便的方法来监视链式方法调用。与tap方法类似,<strong>to_proc</strong>已经在 Ruby 社区中出现一段时间了——Ruby 1.9 预发布版本也具备了这个特性。Ruby 1.9 简单地把它整合在<strong>Symbol</strong>类中,无须任何支持库就可以使用。

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<br></br>puts plus.call(1,2) # prints '3' 由于Symbol类具有to_proc方法,由此所有的符号都可以这样使用:
to_s = :to_s.to_proc<br></br>to_s.call(42) # results in the string "42" ``to_proc的实现很简单。 Dave Thomas (PragDave) 演示了它是如何工作的def to_proc<br></br> proc { |obj, *args| obj.send(self, *args) }<br></br>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 的特性——尽管只存在于最近的修订版中:<strong>Proc#curry</strong>。最近在 ruby-core 中讨论了 Proc#curry 的作用

<span> 它一点也不难,</span><br></br>  proc {|x, y, z| x + y + z }.curry<p><span> 返回一个与下面代码等价的 proc 对象 </span>  proc {|x| proc {|y| proc {|z| x + y + z } } } </p> 这个方法的名字来源于 Currying 的概念,也就是:

[…] 是把带有多个参数的函数转化为带有单个参数的函数(其余的参数由 curry 来决定如何处理)

换 句话说:使用 currying,一个带有 x 个参数的 Proc,可以在调用时使用一个参数。当然,它显然不能返回代码的结果——还差几个参数才能运行代码 ——它返回一个带有 (x - 1) 个参数的新 Proc。就这样一直迭代到最初的 Proc 有了足够的参数,代码才得以运行并返回结果。例如,在同一个 ruby 核线程中,它可以这么用:

plus_five = proc { |x,y,z| x + y + z }.curry.call(2).call(3) <br></br>plus_five[10] #=> 15 注意:plus_five是一个 Proc——操作符 [ ] 被重载来调用它。警告:Proc#curry最近才加入 Ruby 1.9——要试一试的话,你必须使用最近的修订版。

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

2008 年 2 月 28 日 21:56623
用户头像

发布了 33 篇内容, 共 33429 次阅读, 收获喜欢 0 次。

关注

评论

发布
暂无评论
发现更多内容

DDD 实践手册(2. 实现分层架构)

Joshua

设计模式 领域驱动设计 DDD 系统架构 分层架构

阿里巴巴Java开发手册泰山版解读

Bruce Duan

Netty 源码解析(四): Netty 的 ChannelPipeline

猿灯塔

学习来应对创业的未知

Neco.W

创业 重新理解创业

怎样算是一个好的开发者?

水滴

开发者

MySQL中order by语句的实现原理以及优化手段

天堂

Java MySQL 性能优化

韦小宝真的幸福吗 | Random Forest

张利东

Python 学习

消息队列Kafka - acks参数

Java收录阁

kafka

从数据闭环谈微服务拆分

松花皮蛋me

微服务架构 微服务拆分 微服务冶理

说出来就不灵啦

伯薇

糊涂 活在当下 享受状态 生活状态 观察者

把成功过成自己的生活

子铭

成功学 生活状态

InfoQ写作平台首秀,来个自我介绍

nuhcoad

个人感想

MySQL的死锁系列- 锁的类型以及加锁原理

程序员历小冰

MySQL

使用 jsDelivr 免费加速 GitHub Pages 博客的静态资源

mzlogin

CDN Jekyll GitHub Pages 个人博客

如何写作一本书(2):前言与正文

英子编辑

技术 写作

Day 47|Week 07-5 曾国藩家书|问学篇-学问何处何时都可做

熊小北同学

Arthas安装及基本用法

编程随想曲

Java

和邓小平、基辛格“谈笑风生”的世界第一女记者:奥琳亚娜·法拉奇

赵新龙

记者 编辑 采访 法拉奇

浅析 Cocoapods-Packager 实现

Edmond

ruby ios CocoaPods binary packager

Java并发编程系列——锁

孙苏勇

Java Java并发 并发编程 多线程

经济大萧条对我的启示

Neco.W

创业 自我管理 职场 自我提升

我愿沉迷于学习,无法自拔(一)

孙瑜

深度思考 个人成长

下一代存储NVMe over Fabrics

HU

神经网络的激活函数为什么要使用非线性函数

王坤祥

神经网络 激活函数

为什么正在使用的Java版本跟环境变量的版本不一致

阡陌r

Java 踩坑

你真的理解 Java 的基础数据类型吗

Rayjun

Java

“我代码写完了,QA可以测了。”

蔡建斌

Scrum 敏捷 质量管理 测试

多云的一点思考

HU

死磕Java并发编程(7):读写锁 ReentrantReadWriteLock 源码解析

七哥爱编程

Java并发 读写锁 ReentrantReadWriteLock

南丁格尔科普

Sicolas Flamel

如何优雅滴在手机上跑Python代码

王坤祥

Python 移动应用 手机编程

NLP领域的2020年大事记及2021展望

NLP领域的2020年大事记及2021展望

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