文档章节

Ruby 中关于block的一些总结

穿山
 穿山
发布于 2017/11/10 21:58
字数 1564
阅读 71
收藏 0

 在Ruby中块是重点也是难点下面我把这两天学习当中的遇到的知识点做了一些总结。

# 1.1block可以用来做循环
array = %w(This is my blog about Ruby)
array.each{|x| print x + " "}

# 1.2块变量也同样适用多重赋值规则
hash = {x: 'this', y: 'why', z: 'i\'m'}
hash.each{|key, value| print [key,value]}

# 2.1块可以隐藏常规处理
file = File.open("sample.txt")
file.each do |line|
  print line
end
file.close #读取完文件后要将通道关闭,不然会造成IO堵塞

# 2.2 File.open方法中使用块时,在块内部处理完并跳出方法之前文件会自动关闭,这个也是块给我们做的
File.open("sample.txt") do |file|
  file.each_line do |line|
    print line
  end
end

# 2.3上面的代码类似于下面的代码
file = File.open("sample.txt")
begin
  file.each_line do |line|
      print line
  end
ensure
  file.close
end

# 3.1可以替换部分算法
# 使用默认sort方法时没有指定块的时候默认用<=>进行比较
str = %w(This is test about block)
p str.sort

#两者效果相同
p str.sort{|a, b| a <=> b}

#可以通过块来自定义排序
p str.sort{|a, b| a.length <=> b.length}

# 使用sort_by时候先将所有的元素使用length 然后再排序 这样不像上面每调用一次块要执行两次length方法
p str.sort_by{|item| item.length <=> item.length}

# 4.1 定义带块的方法
#使用yield 没有带参数
def foo
  a = 1
  yield a
end

foo {|x| puts x + 2}

#带参数
def foo2 b
  a = 2 * b
  yield a
end

foo2(2){|x| puts x}

#使用 & 和 call 以参数的形式使用块
def bar(&block)
  a = 3
  block.call a
end

bar{|x| puts x**2}

#如果有多个参数的时候 &block 这种类型的参数称为Proc参数
# ruby会把传进来的&block 块封装成Proc对象 这样使用call方法的时候就
#相当于对象调用方法

def bar2(a, b, &block)
  block.call(a, b)
end

bar2(2,'x'){|c, d| puts [c, d]}

# 控制块的执行
# 首先要明确一点break 终止最内部的循环。如果在块内调用,则终止相关块的方法(方法返回 nil)
arry = %w(test hahah in ruby)
def test_break arry
  i = 1
  arry.each do |str|
    print [i, str]
    break if i == 3
    i += 1
  end
  print '测试普通break'
end

test_break arry #break终止循环但还是会执行 print '最后再输出一次'

# 下面测试下break在代码块中
def test_break2 arry
  i = 1
  arry.each do |str|
    puts str
    yield i
    i += 1
  end
  print '测试在block中break'
end
#break在块内则终止相关块的方法 并且可以选择返回参数 此处返回0
p test_break2(arry){|x| break 0 if x == 3}

# next跳到循环的下一个迭代。如果在块内调用,则终止块的执行(yield 表达式返回 nil)。
ary = %w(i l x c b d next)
def test_next arry
  i = 1
  arry.each do |x|
    i += 1
    next if i == 2
    print i,x
  end
  print '我是来测是next的'
end

test_next ary

puts ">>>>>>>>>>>>>>>>>"

def test_next2 arry
  i = 1
  arry.each do |x|
    p yield i, x
    i += 1
  end
  print '测试块内的next'
end
#此处当i=2 时候终止块的执行 就是此次yield的返回值为自定义 但 yield下面的i += 1继续执行
test_next2(ary) do |a, b|
  next "test success" if a == 2
  print a,b
end

# 在块中的return 不是return出代码块 而是return出包含这个代码块的方法
# 重点因为block是代码的集合不是方法
def test_return
  i = 3
  yield i
  print '方法的return'
end

test_return do |x|
  print "我是块中的return 我要return出去了"
  return if x == 3
end

# 块变量可以多重赋值
def block_args_test
  yield()
  yield(1, 2)
  yield(1, 2, 3)
end

#通过一个变量来接收
block_args_test{|a| p [a]}

#通过三个变量来接收
block_args_test{|a, b, c| p [a,b,c]}

#通过|*a|来接受 将所有块变量整合成数组来接收
block_args_test{|*a| p a}

# 将块封装成对象
# 上面我们说过了可以按一下方式将块做为参数
# 因为&参数名 ruby会自动传进来的块封装成Proc对象 称为Proc参数
# 然后通过调用对象的call 来执行代码块的内容
def foo(&block)
  block.call
end

foo{puts '测试一下'}

#定义一个Proc对象 并调用
#两个方法一个是 Proc.new
hello = Proc.new do |name|
  puts "hello i am #{name}"
end

hello.call('ruby')

#proc方法指定块
hello2 = proc do |x|
  print "hello i am #{x}"
end

hello2.call('Java')

#Proc参数一定要放在参数列表的最后一位
def call_each(arry, &block)
  arry.each(&block)
end

call_each(1..4){|n| puts n**2}

# Proc 是能让块做为对象在程序中使用的类
proc = Proc.new {|x| x * 2}
p proc.class
p proc.call(5)

lambda = lambda {|x| x * 2}
p lambda.class #也是proc类

#为何Porc有两个对象 proc和lambda 区别在何处
# 一个中心思想 两大区别
# 都是Proc的实例
# 但proc的行为更像block lambda的行为更像方法

# 区别一 调用时的参数 个数
p p = Proc.new {|x, y| p x,y}
p p.call(1)
p p.call(1, 2)
p p.call(1, 2, 3)

l = lambda {|x,y| p x, y}
# l.call(1) #会报错
p l.call(1, 2)
# p l.call(1, 2, 3) 也会报错
#因为在定义method时候你定义几个变量就传入几个变量 传多传少都会报错
#但block 但如果参数少就nil 补全 多的话就无视

# 区别2
p = Proc.new {|x| return if x > 0}
p p.call(1) #会报错因为此block没有被方法包围 所以无法return出方法

l = lambda {|x| return if x > 0}
p l.call(1) #但lambda就可以被return 因为他的行为更像method

#有些对象有to_proc方法 如果对象以"&对象"的形式传递参数
# 对象.to_proc就会自动被调用 进而生成Proc对象
# 其中符号 Symbol.to_proc方法比较典型
# & 把符号 :capitalize 生成Pro对象
# Proc.new do |arg|
#   arg.capitalize
# end
p arr = %w(a b c)
arr.map(&:capitalize)
#使用符号来代替方法
p "a".capitalize
#method => proc => 利用& 才转成block
p arr.map {|x| x.capitalize }

#附上map each的区别
# each:连续遍历集合中的所有元素,并做相应的操作,原集合本身不会发生变化。
# map: 从集合中获取每个元素,并且传递给块,结果会返回新的数组,原集合发生变化
# collect: 类似于map
# inject:遍历整个集合,并且将集合中的元素,按照一定的方式累计,最后返回一个新的元素,原集合本省不会发生变化。

 

© 著作权归作者所有

穿山
粉丝 9
博文 33
码字总数 18655
作品 0
南京
私信 提问
把玩CocoaPods post_install 和 pre_install

在日常iOS开发中,对CocoaPods使用最长见得形式如下: 但有时候我们想在pod install/update时做一些除了第三方库安装以外的事情,比如关闭所有target的Bitcode功能。这时就要用到CocoaPods中...

CaffreySun
2018/08/29
0
0
浅谈Ruby中的block, proc, lambda, method object的区别

前言 当大家在百度中搜索“block proc lambda”的时候,会出来很多关于这几个概念之间区别的介绍,既然搜索结果中已经有了这些介绍,那为什么还要写这篇文章? 相信看过百度搜索结果中排名靠...

算法与编程之美
2014/10/10
1K
8
【PDF分享】Ruby on Rails 实践.pdf

先看看开头的一段简介,此文写的算是简单明了,非常适合 Rails 入门。 下载 Ruby on Rails 实践.pdf Ruby 简介: 在开始写这个教程之前,我原打算简单介绍一下 Rails 的使用就可以了,网上有...

红薯
2010/09/06
7.3K
6
理解Ruby的4种闭包:blocks, Procs, lambdas 和 Methods。

blocks, Procs, Methods, lambdas(也称闭包)是Ruby中最强大的一部分,用过你就会知道,同时也是最容易迷惑的。 这可能是因为Ruby处理闭包的方式有点怪。更甚的是,Ruby有4种处理闭包的方式,...

孔俊
2013/08/02
42
0
Ruby 的 proc 与 lambda

在一个作用域里,变量名与一组变量值相绑定,改变了作用域,就可以与另一组变量值相绑定,且不影响原作用域的值。使用 查看当前作用域下的变量。 开启作用域的地方称为作用域门(scope gate)...

傅易
2017/12/11
18
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
今天
5
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
今天
6
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
9
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
5
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部