欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

迭代的相关内容

程序员文章站 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
#**********************************************************