Ruby中实现stream

  流是通过延时求值实现的,Ruby中实现stream也是可以做到,可惜就是没有尾递归优化。按照sicp,首要的是两个函数:delay和force:

def mem_proc(exp)
  alread_run=false
  result=false
  lambda{
    if !alread_run
      result=exp.call
      alread_run=true
      result
    else
      result
    end
  }
end
def force(delayed_object)
  delayed_object.call
end
def delay(exp)
  mem_proc(lambda{exp})
end

    delay函数返回延时对象,就是对于未来某个时间求值表达式的承诺;force函数以延时对象为参数,进行相应的求值工作,这里的mem_proc用于记忆已经求值过的表达式。定义stream的constructor和selector函数:

def cons_stream(a,b)
  return a,delay(b)
end
def stream_car(s)
  s[0]
end
def stream_cdr(s)
  force(s[1])
end
def stream_null?(s)
  s.nil? or s==[]
end

    用Ruby中的数组充当“粘合剂”,stream_car直接返回第一个元素,而stream_cdr需要用force求值表达式,履行承诺。另外,将空数组[]作为the-empty-stream。再定义几个高阶函数,map和foreach,其他如filter与此类似:

def stream_enumerate_interval(low,high)
  if low>high
    return []
  else
    cons_stream(low,stream_enumerate_interval(low.succ,high))     
  end
end
def stream_ref(s,n)
  if n==0
    stream_car(s)
  else
    stream_ref(stream_cdr(s),(n-1))     
  end
end
def stream_map(proc,s)
  if stream_null?(s)
    []
  else
    cons_stream(proc.call(stream_car(s)),stream_map(proc,(stream_cdr(s))))    
  end
end
def stream_for_each(proc,s)
  if stream_null?(s)
    :done
  else
    proc.call(stream_car(s))
    stream_for_each(proc,stream_cdr(s))     
  end
end
def display_stream(s)
  stream_for_each(lambda{|item| puts item},s)
end
def stream_filter(pred,s)
  if stream_null?(s)
    []
  elsif pred.call(stream_car(s))
    cons_stream(stream_car(s),stream_filter(pred,stream_cdr(s)))
  else
    stream_filter(pred,stream_cdr(s))   
  end
end

    最后,看下例子:

puts "s:"
s=stream_enumerate_interval(1,5)
display_stream(s)
puts "odd_s:"
odd_s=stream_filter(lambda{|x| x%2==1},s)
display_stream(odd_s)
puts "ss:"
ss=stream_map(lambda{|x|x*x},s)
display_stream(ss)

文章转自庄周梦蝶  ,原文发布时间2008-05-08

时间: 2024-09-24 16:09:40

Ruby中实现stream的相关文章

在Ruby中实现stream

Ruby语言在编程界可以说是一个后起之秀,出现的目的就是帮助编程人员更简便灵活的去编写代码程序,完成自己的功能需求.比如在Ruby实现stream方面. 按照sicp,首要的是两个函数:delay和force: def mem_proc(exp) alread_run=false result=false lambda{ if !alread_run result=exp.call alread_run=true result else result end } end def force(de

ruby中如何调用与局部变量同名的私有方法

    如果ruby中一个局部变量名和私有方法名同名的话,默认该名称被解释为变量而不是方法: x=10; def x;puts "what?" end 当你输入x实际不能执行x方法.解释器只把x解释为变量.而且undef只能对方法而不能对变量下手,所以undef x仍然不行,变量还在那里!一种解决方法是将x方法转换为一个method,然后调用: x_f = method(:x) x_f[] 或者还有一种方法,就是方法别名!你可以指定x的一个别名,这时x肯定会解释为方法: alias n

ruby中的循环语句总结

  这篇文章主要介绍了ruby中的循环语句总结,本文总结了Ruby中常用的一些循环语法,需要的朋友可以参考下 while(当-) 循环 while 条件 语句1; 语句2 ; 语句- end 单行 while 循环 ( 语句1; 语句2 ; 语句- ) while 条件 until(直到-) 循环 until 条件 = while not (条件) for-in 循环 for 变量 in 对象 语句1; 语句2 ; 语句- end break 跳出当层循环 next 忽略本次循环的剩余部分,开始

Ruby中的钩子方法详解

  这篇文章主要介绍了Ruby中的钩子方法详解,本文讲解了什么是钩子方法.included.Devise中的 included.extended.ActiveRecord中的 extended.prepended.inherited等内容,需要的朋友可以参考下 Ruby的哲学理念是基于一个基本的要素,那就是让程序员快乐.Ruby非常注重程序员的快乐,并且也提供了许多不同的方法来实现它. 它的元编程能力能够让程序员编写在运行时动态生成的代码.它的线程功能使得程序员有一种优雅的的方式编写多线程代码.

Ruby中require、load、include、extend的区别介绍

  这篇文章主要介绍了Ruby中require.load.include.extend的区别介绍,require.load用于文件,如.rb等等结尾的文件,include.load则用于包含一个文件中的模块,需要的朋友可以参考下 require,load用于文件,如.rb等等结尾的文件.include,load则用于包含一个文件中的模块. require 一般情况下用于加载库文件,而load则用于加载配置文件. 1.require:加载一个库,并且只加载一次,如果多次加载会返回false.只有当

Ruby中proc和lambda的两个区别

  这篇文章主要介绍了Ruby中proc和lambda的两个区别,本文讲解了在proc和lambda中,return关键字有不同含义.检查参数的方式不同两个重要区别,需要的朋友可以参考下 1.在proc和lambda中,return关键字有不同含义: 在proc中,return仅仅表示从这个lambda中返回. 在lambda中,return不是从proc中返回,而是从定义proc的作用域中返回. 代码如下: def one_method p = Proc.new{return 10} #调用这

进一步深入Ruby中的类与对象概念

  这篇文章主要介绍了进一步深入Ruby中的类与对象概念,包括集成与多态等更多知识点的整理,需要的朋友可以参考下 Ruby是纯面向对象的语言,所有项目似乎要Ruby中为一个对象.Ruby中的每个值是一个对象,即使是最原始的东西:字符串,数字甚至true和false.即使是一个类本身是一个对象,它是Class类的一个实例.本章将通过所有功能涉及到Ruby的面向对象. 类是用来指定对象的形式,它结合了数据表示和方法操纵这些数据,转换成一个整齐的包.在一个类的数据和方法,被称为类的成员. Ruby类的

举例初步讲解Ruby中的正则表达式

  这篇文章主要介绍了Ruby中的正则表达式,是Ruby学习进阶当中的重要知识,需要的朋友可以参考下 正则表达式是一个特殊的字符序列可以帮助匹配或者找到其他字符串或串套,使用的模式保持一个专门的语法. 正则表达式文本是一个模式之间的斜线之间或任意分隔符 %r 如下: 语法: 复制代码 代码如下: /pattern/ /pattern/im # option can be specified %r!/usr/local! # general delimited regular expression

在Ruby中利用Net::SMTP类发送电子邮件的教程

  这篇文章主要介绍了在Ruby中利用Net::SMTP类发送电子邮件的教程,包括类中所带方法的用法介绍,需要的朋友可以参考下 简单邮件传输协议(SMTP)发送电子邮件及路由的e-mail邮件服务器之间的协议处理. Ruby 提供 Net::SMTP 类的简单邮件传输协议(SMTP)客户端的连接,并提供了两个新的方法:new 和 start. new 带两个参数: server name 默认为 localhost port number 默认为熟知的 25 start 方法带有以下这些参数: