迭代的相关内容
程序员文章站
2022-03-02 15:37:19
...
s = "hello"
puts s.enum_for(:each_char).map{|x| x.succ} #=>[i,f,m,m,p]
#enum_for(function_name) 会返回一个枚举器,枚举器可以通过next来自行调用枚举的迭代
#而一般的比如array的each这些方法都会返回一个enumerator
#Enumerator定义了each方法又引入了enumeratable模块,可以使用很多迭代方法
#def each
# loop do
# yield{self.next}
# end
#end
enu=s.enum_for(:each_char)
print enu.next
#外部迭代器来并行迭代
def sequence(*enumerables, &block)
enumerables.each { |element| element.each(&block) }
end
def interleave(*enumerables)
enumerator = enumerables.map { |element| element.to_enum }
while e = enumerator.shift
begin
yield e.next
rescue StopIteration
else
enumerator << e
end
end
end
def bundle(*enumerables)
enumerators = enumerables.map { |element| element.to_enum }
loop {yield enumerators.map { |element| element.next }}
end
a,b,c=[1,2,3],4..6,'a'..'e'
sequence(a,b,c){|x| print x}
interleave(a,b,c){|x| print x}
bundle(a,b,c){|x| print x}
#为了防止迭代器在迭代过程中,数据发生变化,可以先拷贝一份,然后再进行迭代
module Enumerable
def each_in_snapshot &block
snapshot = self.dup
snapshot.each &block
end
end
#当array调用一个没有block的each方法时,他会返回一个enumerator,
# RETURN_ENUMERATOR(ary, 0, 0);而有block时,
#他会去完成代码块的相应任务
puts (1..4).to_a.each_in_snapshot.next
puts (1..4).to_a.each {}.class
#代码块的实参调用更像是并行赋值
{one: 1}.each { |k,v| } #=>k,v=[key, value]
#so
def two
yield 1, 2
end
two{|x| puts x} # x=1,2 => x=1
two{|x,| puts x} # x,=1,2 => x=1
two{|*x| puts x} # *x=1,2 => x=[1,2]
#**********************************************************
#Thread/fibers/continutions
#**********************************************************
thr = Thread.new{}
thr.value #在Thread的block没有执行完之前,thr.value会被挂起
class Fibonacc
def initialize
@x, @y = 0, 1
@fiber = Fiber.new do
loop do
@x, @y = @y, @[email protected]
Fiber.yield @x
end
end
end
def next
@fiber.resume
end
def rewind
@x,@y=0,1
end
end
#可以通过纤程来创建一个有next功能的enumerator
class Generate
def initialize(enumerable)
@enumerable = enumerable
create_fiber
end
def next
@fiber.resume
end
def rewind
create_fiber
end
private
def create_fiber
@fiber = Fiber.new do
@enumerable.each do |ele|
Fiber.yield ele
end
end
end
end
x=Generate.new(5..6)
puts x.next
#纤程与调用纤程的进程间的参数传递
#Fiber如果初始化的时候有行参,那么第一次resume传近来的实参就是她的值
#fiber的代码快的返回值,是最后一次resume的结果
#resume的实参,就是代码块中的yield的结果
f=Fiber.new do |message|
puts "Caller said #{message}"
respond = Fiber.yield("Hello")
puts "Caller said #{respond}"
"Fine"
end
respond = f.resume("Hello")
puts "Fiber said #{respond}"
respond = f.resume("How are you")
puts "Fiber said #{respond}"
#
def line(symbol)
callcc{|c| here=c;puts here}
puts "here"
end
#当here.call时 第一个车here不会被打印出来,因为call只会到连续体的地方,但不会执行里面的代码
#所以会从第二行的here打印开始
#here.call(value)
#那么callcc的返回值就是here
require 'continuation'
class Generate
def initialize
load_generate
end
private
def load_generate
callcc do |c|
@generator_context = c
return
end
loop_generate
end
public
def next
callcc do |c|
@main_context = c
@generator_context.call
end
end
private
#它的作用就是让next可以顺序执行,
#并且可以让loop_generate达到循环的目的
def generate(val)
callcc do |c|
@generator_context = c
@main_context.call(val)
end
end
end
class Fib < Generate
def loop_generate
a, b = 0, 1
loop do
generate b
a, b = b, a+b
end
end
end
fib = Fib.new
puts fib.next
puts fib.next
puts fib.next
puts fib.next
puts fib.next
#**********************************************************
#Thread/fibers/continutions
#**********************************************************
下一篇: Vector的相关内容