流是通过延时求值实现的,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函数:
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
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与此类似:
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
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
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)
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