在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
迭代器: 1、一个Ruby迭代器就是一个简单的能接收代码块的方法(比如each这个方法就是一个迭代器)。特征:如果一个方法里包含了yield调用,那这个方法肯定是迭代器 2、迭代器方法和块之间有如下传递关系:块被当成一个特殊参数传给迭代器方法,而迭代器方法内部在使用yield调用代码块时可将参数值传入块。 3、实际上,迭代器的功能就是一种回调!迭代器方法所属的类只负责遍历需要遍历的元素,而对元素所做的处理则通过回调代码块来实现。 4、Ruby中的容器对象(如数组、Range和Hash对象等)都包含了两个简单的迭代器,分别是each和collect。each可以认为是最简单的迭代器,它会对集合的每个元素调用块。 collect,将容器中的元素传递给一个块,在块中处理后返回一个包含处理结果的新数组。 两个经典例子: # 定义一个Apple类 class Apple # 定义Apple类的构造器 def initialize(name, color, weight) @name = name; @color = color; @weight = weight; end # 使用存储器定义了三个属性 attr :name attr :color attr :weight # 定义一个show方法,该show方法可以作为Apple类的迭代器 def show yield :name , @name yield :color , @color yield :weight , @weight end end # 创建一个Apple实例 apple = Apple.new("红苹果" , "红色" , "0.4") # 使用apple的show迭代器 apple.show do |name , value| puts "这个苹果的" + name.to_s + "变量值是:" + value.to_s end
class Array # 为Array增加一个find方法 def find # 使用for循环迭代数组的所有数组元素 for i in 0...size value = self # yield调用时将数组元素值传入代码块 # 调用结束后将代码块的返回值(boolean值)传回该方法体 return value if yield value end return nil end end # 使用数组的find方法 puts [1, 3, 5, 7, 9].find {|v| v * v > 30 }
块以及闭包: 1、do .... end 这就是一个块,CODE BLOCK,或者叫匿名方法 2、块(block):只是一段代码,相当于一个匿名函数;闭包(Closures):一段代码,能作为参数传递给其它方法。 3、Ruby的4种闭包:blocks, Procs, lambdas 和 Methods。是Ruby中最强大的一部分,同时也是最容易迷惑的。(理解Ruby的4种闭包:blocks, Procs, lambdas 和 Methods。 http://rubyer.me/blog/917 )
4、 ---------------------------------------------------------- 实现迭代器 ---------------------------------------------------------- 英文来自http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html 中文来自http://blog.csdn.net/ruby_cn/article/details/192094 Implementing Iterators 实现迭代器A Ruby iterator is simply a method that can invoke a block of code. At first sight, a block in Ruby looks just like a block in C, Java, or Perl. Unfortunately, in this case looks are deceiving---a Ruby block is a way of grouping statements, but not in the conventional way. 一个Ruby迭代器就是一个简单的能接收代码块的方法(比如each这个方法就是一个迭代器)。第一眼看上去,Ruby中的block像C,Java,Perl中的一样,但是实际上是有不同的。 首先,块在源代码中紧挨着方法调用,并且和这个方法的最后一个参数写在同一行上。其次,这个块不会立即被执行,Ruby首先会记住这个块出现的上下文(局部变量,当前对象等),然后进入方法,这里也是魔术开始的地方。
在方法里面,这个块才会用yield来调用执行,就像这个块是方法本身一样,每当yield在方法中被执行,这个块就会被调用。当这个块执行完退出后,控制将交给yield后面的语句(yield来自一个有20多年历史的语言:CLU)。我们来看一个小例子。 def threeTimes yield yield yield end threeTimes { puts "Hello" } produces: Hello Hello Hello The block (the code between the braces) is associated with the call to the method threeTimes. Within this method, yield is called three times in a row. Each time, it invokes the code in the block, and a cheery greeting is printed. What makes blocks interesting, however, is that you can pass parameters to them and receive values back from them. For example, we could write a simple function that returns members of the Fibonacci series up to a certain value.[The basic Fibonacci series is a sequence of integers, starting with two 1's, in which each subsequent term is the sum of the two preceding terms. The series is sometimes used in sorting algorithms and in analyzing natural phenomena.] 这个块(用两个大括号定义)赋给了一个方法threeTimes,在这个方法里面,yield执行了3次,每次执行它都会调用给定的block,即打印一个欢迎语句。使块变得有趣的是你可以给块传递参数,并且从块中得到结果。下面例子,我们将会得到小于一个指定值得Fibonacci 数列。 def fibUpTo(max) i1, i2 = 1, 1 # parallel assignment while i1 <= max yield i1 i1, i2 = i2, i1+i2 end end fibUpTo(1000) { |f| print f, " " } produces: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 In this example, the yield statement has a parameter. This value is passed to the associated block. In the definition of the block, the argument list appears between vertical bars. In this instance, the variable f receives the value passed to the yield, so the block prints successive members of the series. (This example also shows parallel assignment in action. We'll come back to this on page 75.) Although it is common to pass just one value to a block, this is not a requirement; a block may have any number of arguments. What happens if a block has a different number of parameters than are given to the yield? By a staggering coincidence, the rules we discuss under parallel assignment come into play (with a slight twist: multiple parameters passed to a yield are converted to an array if the block has just one argument).
在这个例子中,yield接收一个参数,这个参数将会在执行的时候传递给指定的块。在块的定义中,参数用两个竖线括起来,放在最前面。在这个例子中f用来接收yield传递的参数,所以,这个块才能打印这个序列。一个块可以接受任意个参数。如果一个块的参数和yield中传递的参数个数不一样,将会怎样呢?很巧合,这和我们在并行赋值(parallel assignment)中谈到的原则一样(如果一个block只接收一个参数,而yield提供的参数多于1个,那么这些参数将被转化为一个数组。) 传递给一个块的参数可以是存在地局部变量,如果是这样的话,那么这个局部变量的新值(如果在块中被修改了)在块退出后将会保留,这可能会有一定的副作用,但是这样做有一个性能方面的考率。
Parameters to a block may be existing local variables; if so, the new value of the variable will be retained after the block completes. This may lead to unexpected behavior, but there is also a performance gain to be had by using variables that already exist.[For more information on this and other ``gotchas,'' see the list beginning on page 127; more performance information begins on page 128.] 一个块也可以返回一个结果给调用它的方法。这个块中的最后一个表达式的值将会返回给方法,Array中的find方法就是这样工作的。(find在
class Array def find for i in 0...size value = self[i] return value if yield(value) end return nil end end [1, 3, 5, 7, 9].find {|v| v*v > 30 } » 7 This passes successive elements of the array to the associated block. If the block returns true, the method returns the corresponding element. If no element matches, the method returns nil. The example shows the benefit of this approach to iterators. The Array class does what it does best, accessing array elements, leaving the application code to concentrate on its particular requirement (in this case, finding an entry that meets some mathematical criteria). 这个用法中数组将连续的元素传递给指定的块,如果这个块返回true,则这个方法返回当前对应的元素值,如果没有符合的值,则返回nil。这个方法显示了迭代器的好处,Array类只作自己应该做的,访问数组元素,而应用代码只关注于特殊的需求。 Some iterators are common to many types of Ruby collections. We've looked at find already. Two others are each and collect. each is probably the simplest iterator---all it does is yield successive elements of its collection. Ruby中的集合对象中也包含其它一些常用迭代器,其中之二是each和collect。each可以认为是最简单的迭代器,它们都会对集合的每个元素来调用块。 [ 1, 3, 5 ].each { |i| puts i } produces: 1 3 5
The each iterator has a special place in Ruby; on page 85 we'll describe how it's used as the basis of the language's for loop, and starting on page 102 we'll see how defining an each method can add a whole lot more functionality to your class for free. 另一个是collect,它跟each类似,它将集合中的元素传递给一个块,在块中处理后返回一个包含处理结果的新数组。 ["H", "A", "L"].collect { |x| x.succ } » ["I", "B", "M"]
其他: 关于 迭代器 Iterators 的解释:RUBY 使用手册:http://guides.ruby.tw/ruby/iterators.html 深入理解Blocks,Procs和lambdas http://blackanger.blog.51cto.com/140924/123034 在Ruby中实现迭代器 http://free-dem.iteye.com/blog/218123 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论