Ruby中使用连续体Continuation实现生成器_ruby专题

ruby中有很多经典的驱动器结构,比如枚举器和生成器等.这次简单介绍下生成器的概念.生成器是按照功能要求,一次产生一个对象,或称之为生成一个对象的方法.ruby中的连续体正好可以用来完成生成器的功能.连续体说起来晦涩,其实还是很简单的,它有3个特点:

1. callcc方法会给代码块传一个连续体对象,你可以保存该对象;
2. 当调用连续体的call方法时指令流会跳转到callcc方法之后;
3. 如果给连续体的call方法传递对象,则callcc方法会返回该对象,如果不传递对象,callcc会返回nil.

我们下面参考一段实例代码,我加了注释.该代码用来生成Fibonacci数列和一个递增数列.两个类FibG和IncG都继承于"抽象类"G,G实现生成器的"抽象"事件驱动逻辑,而具体类FibG和IncG用来完成实际生成逻辑,全在代码里啦:

复制代码 代码如下:

#!/usr/bin/ruby

require 'continuation'

#一个生成器"抽象"类
class G
 def initialize
  do_g
 end
 
 #@main_context实际是next的"出口",让next返回@main_context.call(v)的值,即生成的数
 def next
  callcc do |c|
   @main_context = c
   @g_context.call
  end
 end
private
 def do_g
  callcc do |c|
   @g_context = c
   return
  end
  g_loop #虚方法,由实际具体类实现,但由G来调用!
 end

 #@g_context实际为G的内在驱动器,其会反复回到g_loop中不断生成新的数
 def g(v)
  callcc do |c|
   @g_context = c
   @main_context.call(v)
  end
 end
end

#具体的生成器类,用来生成Fibonacci数列
class FibG < G
private
 #具体类实现g_loop,实际要怎么生成必须由具体类说了算
 #g_loop不能直接由FibG的实例对象调用,而要通过G来驱动
 def g_loop
  g(1)
  a,b=1,1
  loop do
   g(b)
   a,b=b,a+b  
  end
 end
end

class IncG < G
 def initialize(inc_val=10)
  super()
  @inc_val = inc_val
 end
<span style="font-size:18px;"></span><pre name="code" class="ruby">private 
 def g_loop
  x=0
  loop do
   g(x+@inc_val)
   x+=@inc_val
  end
 end
end

f = FibG.new
100.times {printf "%d " % f.next}
puts

i = IncG.new
100.times {printf "%d " % i.next}
puts

i = IncG.new(11)
100.times {printf "%d " % i.next}

时间: 2024-08-02 01:39:48

Ruby中使用连续体Continuation实现生成器_ruby专题的相关文章

Ruby中Time对象的常用函数总结_ruby专题

时间对象. Time.now返回当前时间. 1.Time.at Time.at(time[, usec]) 返回time所指时间的Time对象. time可以是Time对象,也可以是表示自起算时间以来的秒数的整数或浮点数. 若浮点精度不够时,可以使用usec. 它将返回time +(usec/1000000)所表示的时间. 此时,time和usec都必需是整数. 生成的Time对象将使用地方时的时区. 2.Time.gm.Time.utc Time.gm(year[, mon[, day[, h

Ruby中Block和迭代器的使用讲解_ruby专题

我们来简单地描述Ruby的一个独特特性.Block,一种可以和方法调用相关联的代码块,几乎就像参数一样.这是一个不可思议的功能强大的特性. 可以用Block实现回调(但它比Java的匿名内部(anonymous inner)类更简单),传递一组代码(但它远比c的函数指针灵活),以及实现迭代器. Block只是在花括号或者do...end之间的一组代码. {puts "Hello"} #this is a block do ### club.enroll(person) #and so

Ruby中操作字符串的一些基本方法_ruby专题

 在Ruby中的String对象持有和操纵的任意序列的一个或多个字节,通常表示人类语言的字符表示. 简单的字符串文本括在单引号(单引号字符).引号内的文本的字符串值: 'This is a simple Ruby string literal' 如果需要内放置一个单引号,单引号的字符串文字,在它前面加上一个反斜杠Ruby解释器不认为终止字符串: 'Won\'t you read O\'Reilly\'s book?' 反斜杠也可以转义另一个反斜杠,这样第二个反斜杠本身不是解释为转义字符. 以下是

Ruby中的循环语句的用法教程_ruby专题

 Ruby中的循环用于执行相同的代码块指定的次数.本章将详细介绍Ruby支持的循环语句.Ruby while 语句:语法: while conditional [do]    code end 执行代码当条件为true时.while循环的条件是代码中的保留字,换行,反斜杠(\)或一个分号隔开. 实例: #!/usr/bin/ruby $i = 0 $num = 5 while $i < $num do puts("Inside the loop i = #$i" ) $i +=1

Ruby中关于模块的一些基础知识_ruby专题

模块与类很相似,它也可以说成是"不能被实例化的类".由于Class类是Module类的子类,所以说成是"类=模块+实例化能力"也许更好. 所谓模块,究竟是用来干什么的呢?其作用主要有两大类:Mix-in和命名空间. Mix-in实际上是受限制的多重继承.利用实际做成的继承关系,可以实现对某些类进行一些"点缀"的目的.事实上,Mix-in这种说法就来自于在冰激凌上面的饼干或者坚果. 在面向对象设计的历史中,由多重继承机制造成的问题早已众所周知了.所

详解Ruby中的单件方法和单件类_ruby专题

单件方法 Ruby允许给单个对象增加方法,这种只针对单个对象生效的方法,称为单件方法 示例代码 str = "just a regular string" def str.title? self.upcase == self end str.title? # => false str.methods.grep(/title?/) # => [:title?] str.singleton_methods #=> [:title?] str.class # => S

Ruby中的block代码块学习教程_ruby专题

1.什么是代码块在Ruby中,{}或do...end之间的代码是一个代码块.代码块只能出现在一个方法的后边,它紧接在方法最后一个参数的同一行上,由yield关键字调用.例如: [1,2,3,4,5].each { |i| puts i } [1,2,3,4,5].each do |i| puts i end 块变量:以yield关键字调用block也可以传递参数,block中竖线(|)之间给出的参数名用于接收来自yield的参数.  竖线之间(如上例中的 | i |)的变量被称作块变量,作用和一

在Ruby中处理日期和时间的教程_ruby专题

Time 类在 Ruby 中用于表示日期和时间.它是基于操作系统提供的系统日期和时间之上.该类可能无法表示 1970 年之前或者 2038 年之后的日期. 本教程将让您熟悉日期和时间的所有重要的概念.创建当前的日期和时间 下面是获取当前的日期和时间的简单实例: #!/usr/bin/ruby -w time1 = Time.new puts "Current Time : " + time1.inspect # Time.now 是一个同义词 time2 = Time.now puts

Ruby中检测Gem是否安装的方法_ruby专题

最近参加七牛的demo大赛,决定使用ruby开发.于是遇到了一些疑问,然后解决了,这里记录一下. 在Ruby中,Gem是一个很常见的东西,其相当于插件,Ruby有很多很棒的gem,避免了我们重复造轮子,我的demo中需要安装gem,但是为了更加实现好一些,先检测gem是否已经安装,如果没有安装,在继续安装,否则不安装. 于是,怎么在Ruby中检测gem是否安装呢,其实也很简单,直接上代码就可以了.不需太多解释.begin-rescue-相当于java中的try catch. 复制代码 代码如下: