Day11 - Ruby的block,proc,lamdba方法比较
前情提要:
第11天开始,要更深入Ruby的精髓!
Ruby经典面试题目#11
Ruby的block,proc,lamdba方法比较?What’s difference between blocks,procs and lambdas?
block代码内存块
代码内存块是用do…end围起来,围出特定一个区域、放代码的地方。
就好像跑马拉松一样,道路上会进行交通管制,把参赛者的跑道围起来。
do…end的形式常常使用在数组和循环里,把数组想成参赛者的列表,循环想成跑道,每个参赛者(数组内的元素)都要一个一个进入跑道(循环),是不是就很好理解了呢?
block: do…end
我们来用do…end围出block。昨天提到ruby invoke method的阶层有五层:
find_method = [“Class”,“Module”,“Object”,“Kernel”,“BasicObject”]
find_method.each do |find_method|
p find_method
end
结果显示为:
Class
Module
Object
Kernel
BasicObject
block: {}
假如某个特定参赛者选手如我,每年都一次马拉松,而2018年即将跑第3次啦!我可以用大括号{}印出如下:
3.times {p“I love running 42K marathon!”}
因为很重要所以喊3次,这个大括号{}围出的内存块,忠实地印出(chao-ok-huangdaoyi):
“I love running 42K marathon!”
“I love running 42K marathon!”
“I love running 42K marathon!”
有没有注意到,不管是do…end,还是{},前面都跟着method呢?
do…end前有.each这个Array里的方法;{}前有.times这个属于Integer的方法。
所以,重点出现:block不是物件!必须跟在其他的方法或物件之后。
3.times {p“block is not Object!!!“} #很重要所以说3次
block: yield
人生就像马拉松一样漫漫长路。有的时候跑步跑累了,我们需要喝点水、休息喘口气。那该如何用block表示呢?我们使用yield方法呼叫:
def keep_running
p“-start line-”
yield #block
p“-finish line-”
end
keep_running {
p“drink water”
}
结果显示为:
-start line-
drink water
-finish line-
在ruby on rails项目里,我们也很常在erb档名下,发现这种利用yield方法,调用代码内存块的页面:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv=“Content-Type”content=“text/html;charset=utf-8”/>
</head>
<body>
<%= yield %>
</body>
</html>
其中<%= yield %>就是在html页面代入ruby代码的内存块。关于更多yield说明,可以参考Ruby on Rails Guide.
Proc程序物件
Proc是程序物件,跟block一样可放入程序内存块。
在Ruby API里,定义:
Proc objects are blocks of code that have been bound to a set of local variables.
方刚我说明到block不是物件,因此如果我们遇到需要一次处理很多的block,或是多次使用一个block的情况时,与其重复写code,不如把需要重复的部分写成物件。
我现在想进一步利用Proc放入程序判断,计算在马拉松赛事、半马和全马分别跑过几公里。
首先用block列出参赛纪录:
place = [“2012太鲁阁半马”,“2012玉山半马”,“2013万金石半马”,“2013双溪半马”,“2013台北市半马”,“2014黄金海岸半马”,“2014 Perth半马”,“2016 Sydney全马”,“2017 Melbourne全马”,“2018大堡礁全马”]
place.each do |place|
puts place
end
block显示出,凡跑过必留下痕迹!
2012太鲁阁半马
2012玉山半马
2013万金石半马
2013双溪半马
2013台北市半马
2014黄金海岸半马
2014 Perth半马
2016 Sydney全马
2017 Melbourne全马
2018大堡礁全马
以上纪录显示,从2012-2018年,半马(21KM)跑过7次,全马(42K)跑3次。由于block无法代入参数,此时Proc就派上用场了!
Proc的类别方法
来写我人生第一个使用Proc物件的跑步方法proc_running。
在这个类别方法(class method)内,用.new产生新的程序物件。
在方法之外,用{}大括号围出block,用.call方法呼叫程序物件proc本身:
def proc_running
Proc.new
end
proc = proc_running {“I love running!”}
p proc.call #=>“I love running”
来看看Proc代入参数之后,可以做的事就变多啰,我现在想计算半马(21KM)跑过7次,全马(42K)跑3次,分别是几公里:
def count_km(km)
return Proc.new {|n| n*km}
end
full_marathon = count_km(42)#126
half_marathon = count_km(21)#147
p“I've run #{half_marathon.call(7)} Km in Half Marathon and #{full_marathon.call(3)} Km in Marathon”
还记得#{}可以帮我们插入字串吗?(此方法会先利用to_s将传入的Integer成String格式)
所以计算答案揭晓:
“I've run 147 Km in Half Marathon and 126 Km in Marathon”
Proc的实体方法
Proc可以new出新的程序物件实体km_proc:
km_proc = Proc.new { |km,*n| n.collect { |n| n*km } }
p km_proc.call(42,1,3)#=> [42,126]
p km_proc.call(21,1,7)#=> [21,147]
这样我就可以把计算的跑步公里数,美美地用.collect这个数组方法裱框印出来!
[42,126]
[21,147]
观察刚刚的类别方法,我们发现Proc可以代入参数,也可以用return回传参数,那我想要仿造文章前头这段block代码概念:
def keep_running
p“-start line-”
yield #block
p“-finish line-”
end
keep_running {
p“drink water”
}
写一个喝水Proc程序:
def proc_keep_running
p“-start line-”
water_proc = Proc.new { return“drink water”}
water_proc.call
p“-finish line-”
end
p proc_keep_running
# Prints“-start line-”but not“-finish line-”
结果印出:
-start line-
drink water
疑?怎么喝完水就打住,不继续跑向终点-finish line-呢?
我们发现了:
在proc内使用return会立即返回,不再继续执行后面程序。
(所以,永远不能在Proc内使用return,这样跑马拉松会无法抵达终点啊啊啊啊!)
lambda匿名函数
身为工程师,问题代表着机会;出现问题就代表会有解决方案的出现,在Proc中有一个特别的用法叫lambda。创建方法有两种指令:lambda or ->()
lambda_running = lambda { puts“Run with lambda!”}
lambda_running = -> { puts“Run with lambda!”}
如果我们使用puts印出,会发现lambda是Proc的一种:
p lambda_running
#<Proc:0x000056043ddfd1e8@main.rb:11(lambda)>
我们来用基本的程序语法,比较proc与lambda回传值:
刚刚说到Proc方法内不能放return,
def proc_run
proc = Proc.new { return }
proc.call
p“Run with Proc!”
end
proc_run #跑不出来“Run with Proc”结果!
但lambda可以:
def lambda_run
lam = -> { return }
lam.call
p“Run with lambda!”
end
lambda_run #=>“Run with lambda!”
从下文说明,我们可以了解Proc只会回传目前阶层的内容,而不会像一般的方法以及lambda匿名方法一样,整个走完方法里面的该回传的值。
The difference between procs and lambdas is how they react to a return statement.A lambda will return normally,like a regular method.But a proc will try to return from the current context.The reason is that you can’t return from the top-level context.出处
现在来用lambda的两种调用写法lambda or ->()练习写作代码,分别回传半程马拉松(hm)和全程马拉松(fm)的公里数(leafor):
half_proc = lambda {|hm,fm| hm}
full_proc = ->(hm,fm){fm}
p half_proc.call(21,42)#21
p full_proc.call(21,42)#42
结果half_proc.call会回传21,full_proc.call会回传42。
如果参数多放一个呢?1.5个马拉松
p full_proc.call(21,42,63)
会出现错误讯息:
main.rb:17:in `block in <main>':wrong number of arguments(given 3,expected 2)(ArgumentError)
这个原因在于:
lambda是方法,所以它会检查参数个数是否匹配。
来用程序举例一下:
lambda_argument = lambda {|x| x*2}
p“Lambda result: 21Km *2= #{lambda_argument.call(21)}Km”
proc_argument = Proc.new {|x,y|“I don't care how many arguments inside Proc!”}
p“Proc result: #{proc_argument.call(21,42,63)}”
结果印出:
“Lambda result: 21Km *2= 42Km”
“Proc result: I don't care how many arguments inside Proc!”
超级比一比的表格又出现了:
block程序内存块Proc程序内存块物件lambda匿名方法
不是物件带名字的内存块物件,可储存变数和Proc类似,但更加接近method方法
不是参数可带参数严格检查参数数目
N/A在Proc里return其他值,会离开此物件的方法在lamba里return其他值,会回来继续执行完方法
最后的最后,我们用lambda来写马拉松喝水的方法吧!
def lambda_keep_running
p“-start line-”
water_lambda = lambda { return“drink water”}
p water_lambda.call
p“-finish line-”
end
lambda_keep_running
结果印出:
-start line-
drink water
-finish line-
顺利迎向终点finish line了!
也祝大家都能顺利完赛!!!:)
转载于:https://www.cnblogs.com/lannyQ-Q/p/10804659.html
Day11 - Ruby的block,proc,lamdba方法比较相关推荐
- Ruby 之 Block, Proc, Lambda 联系--区别,转载
Ruby 之 Block, Proc, Lambda Block Block 不是对象,是Ruby的语言特性,近似于闭包(Closure). 范例: def meth res= yield ...
- iOS之深入解析如何使用Block实现委托方法
一.前言 Block 和 Delegate 是对象间传递消息的常用机制,这两个机制可以说是各有千秋. Delegate 可以很方便把目标动作的执行过程划分为多个方法,以展现不同时间节点下特定的操作:B ...
- Ubuntu开机出现“error: invalid environment block“的解决方法
Ubuntu开机出现"error: invalid environment block"的解决方法 1. 错误状态 2. 解决办法 1. 错误状态 当使用GRUB启动ubuntu时 ...
- yum安装ruby_CentOS 7下配置Ruby语言开发环境的方法教程
本文跟大家分享的是在CentOS 7下配置Ruby语言开发环境的方法教程,分享出来供大家参考学习,下面来看看详细的介绍: 安装Ruby 2.2 CentOS7存储库中的Ruby版本为2.0,但如果需要 ...
- 微信小程序手机号解密报错:pad block corrupted 解决方法
微信小程序手机号解密报错:pad block corrupted 解决方法 微信小程序获取用户手机号,后端解密手机号的时候偶尔会报错 javax.crypto.BadPaddingException: ...
- ruby语法_Ruby函数(方法)语法
ruby语法 The Ruby language makes it easy to create functions. Ruby语言使创建函数变得容易. Function Syntax 功能语法 de ...
- Vivado System Generator for DSP - “Error evaluating ‘OpenFcn‘ callback of Xilinx Block“错误解决方法
使用Vivado System Generator for DSP时,遇到"Error evaluating 'OpenFcn' callback of Xilinx Block" ...
- 用pry阅读ruby源码--以task方法为例
rails项目中有个目录 lib/tasks,里面定义了一个rake任务: task hello: :hello do puts "hello" end 看到这里的时候,是不是可能 ...
- 微信小程序解密encryptedData报错:pad block corrupted 解决方法
今天碰到一个pad block corrupted错误,跟代码发现是Cipher里面的doFinal()爆出的错. 代码: public static JSONObject getUserInfo(S ...
最新文章
- 基于 HTML5 WebGL 的 3D 棉花加工监控系统
- 关于JQ的点击事件在微信手机端无响应的解决方案
- allowedExts php,通过php扩展增加一个内置函数
- 语音识别热词_出门问问 TWS 耳机语音交互解决方案
- AtomicInteger 的使用
- 《Pro ASP.NET MVC 3 Framework》学习笔记之一【MVC的历程,优点,HelloWorld】
- ubuntu使用git时,终端不显示git分支。
- 分类 Classification
- 【云分析】之一《公有云对企业发展战略的影响》
- 18年12月英语六级第二套听力单词
- AWSome Day 2019 线上云技术课堂(2)
- 高等数学——变限积分求导
- [经]信用体系,金融改革
- java 函数 throw_java为什么有些异常throw出去需要在函数头用throws声明,一些就不用。...
- 新买的电脑硬盘如何分区
- 高数--函数--初等函数
- 第一代真空电子管计算机主要应用范围是,计算机应用基础知识课件.ppt
- 【树莓派】树莓派SD卡测速一键脚本,SD卡读写速度测试程序
- 网页使用思源字体 CSS
- 多径效应(multipatheffect)
热门文章
- java没有编译器吗_java有编译器吗
- 艺赛旗开发技巧-根据文本点击网页元素
- 【poj 3069】萨鲁曼的大军
- 【亲测有效】解决执行nrm ls命令查看不到*星号的问题
- [转]ESMTP的三个认证方式: CRAM-MD5 PLAIN和LOGIN
- 2015最新经典语句搞笑段子
- Workspace Cannot Be Created
- Mac OS X: MS Office 2008 Preference Manifests
- 虚拟机无法启用 虚拟化引擎 Inter VT-x/EPT,mumu模拟器报错Hyper-v 开启,无法启动模拟器
- QCC305x系列开发教程(入门篇)之1.2-安装开发中需要配套软件