一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

ruby系列教材(24):Implementing Iterators

 漂在北方的狼 2006-12-06

Block的內(nèi)部調(diào)用過程:

 

調(diào)用method three_times的時候,遇見yield,就立即調(diào)用Block,block運行完畢,馬上返回yield的下一句

 

method_name(parameter,parameter){block}

這里,解釋器遇見method_name(parameter,parameter)就進入method_name(parameter,parameter)的定義體,運行,當(dāng)遇見block的時候,就執(zhí)行{}中的內(nèi)容,也就是解釋器遇見method_name(parameter,parameter)時候并不關(guān)心后面的內(nèi)容,也就是block的內(nèi)容,只是在運行遇見yield statement的時候才轉(zhuǎn)到block這里,所以在class里面定義以后,調(diào)用時候必須時候,否則將出現(xiàn)錯誤:

def test

  yield

end

test

 

結(jié)果:

in `test‘: no block given (LocalJumpError)
    from -:4

 

不過這里說了:ruby解釋器,先了解method_name(parameter,parameter)就進入class definition,遇見yield就運行block,所以下面的代碼也是合法的:

def test

   p "run"    #沒有yield,也可以運行

end

test{}

 

結(jié)果:

run

 

 

Block可以接收一個來自yield處的變量,也可以返回一個值

1)Block接收值

值(value)來源于yield,例如
def fib_up_to(max)

  i1,i2 = 1,1                                      # parallel assignment (i1 = 1 and i2 = 1)

  while i1 <= max

    yield i1                                         #i1講被傳遞到block里面

    i1,i2 = i2,i1+i2

  end

end

 

fib_up_to(1000){|f| print f," "}        #i1的值賦值給f,表現(xiàn)就是i1的值傳遞到了block里面的f了,使用|variable|來接受值

 

關(guān)于block的應(yīng)用我們很久以前就說過了,假如yield有2個parameters,那么這里要用|para1,para2|這樣的形式

 

前面我們提過,不能從語法的角度來理解ruby,要從語意的角度理解ruby,因為ruby是一門更加貼近問題域的語言

這里yield i1有一層語意就是,我要把 i1 這個值傳遞給一個block

 

我們下面看一段程序:

a = [1,2]
b = ‘cat‘
a.each{|b| c = b * a[1]}


問題出現(xiàn)了,1)a,b在括號里面出現(xiàn),會不會改變其值 2)c在括號外面可以用嗎?

 

結(jié)果是:

a→[1, 2]

b→2                        #值被括號內(nèi)改變

defined?(c)→nil        #c沒有被定義,也就是c出了括號,就沒有了

 

事實上有2條規(guī)則:

a. block外面的variables出現(xiàn)在block內(nèi)部,內(nèi)部將直接改變值

b. block外面的variables沒有出現(xiàn)在block內(nèi)部,這時候的variables作用域僅僅在這個block內(nèi)或者說是屬于這個block

 

這樣我們得到了block和外部環(huán)境交互的能力,但是這樣的方式也遭到了很多的質(zhì)疑,也許會改今后的版本中進行一定的調(diào)整

 

*注意,一般的情況,比如find,each,times這些迭代器都是從0開始到max結(jié)束

find 適用于Array,yield帶有1個parameter,迭代過程從0-array.length,返回值是element類型(or nil)
each 適用于Array,yield帶有1個parameter,迭代過程從0-array.length,返回值是這個array本身
times 適用于Fixnum,yield帶有1個parameter,迭代過程從0-(num-1),返回值是這個fixnum

上面的總結(jié)不全面,注意,對于each,times我們根本不關(guān)注他們的返回類型

 

 

2)Block返回值

一個block可以返回一個值,可以認(rèn)為一個yield(parameter,parameter)可以返回一個值,這個值是block中,最后一次賦值的表達(dá)式的值(同于methods)

 

我們前面提到過find iterator,可能大家會覺得有些迷惑,它的實現(xiàn)如下:

class Array

  def find

    for i in 0...self.length             #self表示引用它的object

      value = self[i]

      return value if yield(value)  #yield返回一個值,這里返回的是一個true or false

    end

    return nil

  end

end

 

*上面的self.length可以寫成 size,表示引用它的對象的大小

 

self 表示應(yīng)用這個method的object,例如,在method里面有self,123.method_name 這個時候,self表示123這個object

 

yield 有什么好處呢?yield實現(xiàn)了代碼級的復(fù)用,我們一般來說,實現(xiàn)的是method級別的復(fù)用,也就是復(fù)用方法,而yield提供了這樣的能力,使得我們重復(fù)出現(xiàn)的代碼都消失了,這是十分神奇的

 

 

Iterator:(一般來說只要是collection就有他的iterators)

1)each

遍歷array中的所有element,對于array來說,可以這樣用:

[1,2,3,4,5].each{|i| p i}

 

對于File class each iterator每次從file object里面每次讀出一行:

f =  File.open("testfile")

f.each do |line|              #一次讀出一行

  puts line

end

f.close

 

2)collect

和each一樣進行遍歷,但是collect將所有的block的返回值收集起來,建立一個array object返回,例如:

num = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
num2 = num.collect do |i|
    if i%2==0
        i
    else
        []
    end
end

num2.each{|i| print i," "}

 

結(jié)果:

 2  4  6  8  10  12  14 

 

3)inject

inject可以帶parameter,inject的parameter和yield的parameter有一定的關(guān)系,yield有2個parameters

object.inject(a){|p1,p2| p1+p2}

這個表示p1初始化為a,p1以后的值為block的返回值,p2是object elements的值,一直遍歷過去

舉例說明:

print [1,2,4,9].inject(0){|sum,ele| sum+ele}    #結(jié)果:16

print [1,2,4,9].inject(1){|sum,ele| sum*ele}     #結(jié)果:72

 

inject也可以不帶parameter,這個時候,yield第一個parameter的值為array object第一個element的值,yield第2個parameter的值是array object的第2個element的值,比如:

print [1,2,4,9].inject{|sum,ele| sum*ele}     #結(jié)果:72    .............1)

print [1,2,4,9].inject{|sum,ele| sum+ele}    #結(jié)果:16     .............2)

1)中sum初始化的值是1,ele最初值是2

2)中sum初始化的值是1,ele最初值是2

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美日韩免费黄片观看| 亚洲夫妻性生活免费视频| 我要看日本黄色小视频| 精品欧美在线观看国产| 国产中文字幕一二三区| 东京热加勒比一区二区三区| 日韩中文无线码在线视频 | 欧美日本亚欧在线观看| 伊人久久青草地综合婷婷| 久久人妻人人澡人人妻| 91人妻久久精品一区二区三区| 在线视频三区日本精品| 东京热男人的天堂一二三区| 黄色污污在线免费观看| 91亚洲熟女少妇在线观看| 国产精品人妻熟女毛片av久久| 亚洲熟女乱色一区二区三区 | 欧美一区二区口爆吞精| 亚洲高清中文字幕一区二三区| 大香蕉伊人一区二区三区| 国产精品欧美一区两区| 亚洲一区二区亚洲日本| 91熟女大屁股偷偷对白| 韩国激情野战视频在线播放| 日韩精品一区二区不卡| 亚洲国产精品久久琪琪| 真实偷拍一区二区免费视频| 大香伊蕉欧美一区二区三区| 亚洲欧美日本视频一区二区| 欧美日韩国产精品第五页| 欧美日韩中黄片免费看| 国产一二三区不卡视频| 爱草草在线观看免费视频| 成年人黄片大全在线观看| 九九热这里有精品20| 久久亚洲国产视频三级黄| 欧美成人免费一级特黄| 内射精品欧美一区二区三区久久久 | 色一情一乱一区二区三区码| 东北老熟妇全程露脸被内射| 暴力性生活在线免费视频|