小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

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)就進(jìn)入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)就進(jìn)入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ì)疑,也許會改今后的版本中進(jìn)行一定的調(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一樣進(jìn)行遍歷,但是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ā)表

    請遵守用戶 評論公約

    類似文章 更多