写点什么

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:56676
用户头像

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

关注

评论

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

区块链一新基建 新动能 新发展大会将在南昌举办

CECBC区块链专委会

新基建 区块链技术

手把手教你从零开始使用python编写大型冒险类游戏01之游戏介绍

Geek_8dbdc1

Dubbo2.7试用

心平气和

dubbo 灰度 hessian

Django的Models更新时,不触发Signals解决办法

BigYoung

django singals 信号机制 update 更新

芯片破壁者(十二.下):青瓦台魔咒与半导体“死亡谷”

脑极体

非科班学习编程一定得知道这几个网站!

我是程序员小贱

为什么修改hosts不立即生效?--浏览器DNS缓存机制分析

陈磊@Criss

Serverless:为我们到底带来了什么

刘宇

Serverless 云原生

源码分析 | 咋嘞?你的IDEA过期了吧!加个Jar包就破解了,为什么?

小傅哥

Java 字节码插桩 asm bytebuddy

Python中的单下划线和双下划线使用场景

王坤祥

Python Python基础知识 Python基础

[修复 Webpack 官方 Bug] 提取CSS时的依赖图修正

分一

前端 webpack 编译优化 源码刨析

图解23种设计模式——前方高能,前端切图仔请务必抓好方向盘

执鸢者

typescript 前端 设计模式

Git设置分支保护实现CodeReview卡点

陈磊@Criss

MySQL-技术专题-InnoDB存储引擎

李浩宇/Alex

office 365激活,总是自动变成专业版2019

wood

Office Office 365

从北京降雨的复盘中,我发现了企业SD-WAN网络的秘密

脑极体

中本聪原始比特币论文解读:点对点的电子现金系统

韩超

比特币 区块链

Go: Goroutine, 系统线程和CPU管理

陈思敏捷

go golang mpg

2.3.2 JDK动态代理 -《SSM深入解析与项目实战》

谙忆

Windows AD 保姆级配置NTP服务器教程

BigYoung

时间 AD ntp Windows Server 2012 R2

用故事去理解「文件 I/O」

小林coding

操作系统 异步 文件系统 同步 非阻塞网络I/O

Git命令可视化展示,代码管理再也不愁了,建议收藏!

诸葛小猿

git git merge git rebase git fetch git reset

MySQL 架构与历史

多选参数

MySQL 数据库 MySQL优化

契约测试:解决微服务测试的问题

陈磊@Criss

想要成功,你需要的是目标与动机,目标是你的助攻,动机是你的爱人。

叶小鍵

成功学 心理学 海蒂·格兰特·霍尔沃森

记一次腾讯云(西安)后台开发面试经历

z小赵

面试 分布式 高并发

数据治理第一步,摆脱“手工作坊”

KAMI

大数据 数据治理 数据开发 数据平台

微博基于 Flink 的机器学习实践

Apache Flink

flink

Flink 中的应用部署:当前状态与新应用模式

Apache Flink

flink

手撕二分查找及其变种,就是干!

我是程序员小贱

一文了解对称加密与非对称加密

我是程序员小贱

安全

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