国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

directory search
Ruby用戶指南 3、開始 4、簡單的例子 5、字符串 6、正則表達式 7、數(shù)組 8、回到那些簡單的例子 9、流程控制 10、迭代器 11、面向?qū)ο笏季S 12、方法 13、類 14、繼承 15、重載方法 16、訪問控制 17、單態(tài)方法 18、模塊 19、過程對象 20、變量 21、全局變量 22、實變量 23、局部變量 24、類常量 25、異常處理:rescue 26、異常處理:ensure 27、存取器 28、對象的初始化 29、雜項 RGSS入門教程 1、什么是RGSS 2、開始:最簡單的腳本 3、數(shù)據(jù)類型:數(shù)字 4、數(shù)據(jù)類型:常量與變量 5、數(shù)據(jù)類型:字符串 6、控制語句:條件分歧語句 7、控制語句:循環(huán) 8、函數(shù) 9、對象與類 10、顯示圖片 11、數(shù)組 12、哈希表(關(guān)聯(lián)數(shù)組) 13、類 14、數(shù)據(jù)庫 15、游戲?qū)ο?/a> 16、精靈的管理 17、窗口的管理 18、活動指令 19、場景類 Programming Ruby的翻譯 Programming Ruby: The Pragmatic Programmer's Guide 前言 Roadmap Ruby.new 類,對象和變量 容器Containers,塊Blocks和迭代Iterators 標(biāo)準(zhǔn)類型 深入方法 表達式Expressions 異常,捕捉和拋出(已經(jīng)開始,by jellen) 模塊 基本輸入輸出 線程和進程 當(dāng)遭遇挫折 Ruby和它的世界 Ruby和Web開發(fā) Ruby Tk Ruby 和微軟的 Windows 擴展Ruby Ruby語言 (by jellen) 類和對象 (by jellen) Ruby安全 反射Reflection 內(nèi)建類和方法 標(biāo)準(zhǔn)庫 OO設(shè)計 網(wǎng)絡(luò)和Web庫 Windows支持 內(nèi)嵌文檔 交互式Ruby Shell 支持 Ruby參考手冊 Ruby首頁 卷首語 Ruby的啟動 環(huán)境變量 對象 執(zhí)行 結(jié)束時的相關(guān)處理 線程 安全模型 正則表達式 字句構(gòu)造 程序 變量和常數(shù) 字面值 操作符表達式 控制結(jié)構(gòu) 方法調(diào)用 類/方法的定義 內(nèi)部函數(shù) 內(nèi)部變量 內(nèi)部常數(shù) 內(nèi)部類/模塊/異常類 附加庫 Ruby變更記錄 ruby 1.6 特性 ruby 1.7 特性 Ruby術(shù)語集 Ruby的運行平臺 pack模板字符串 sprintf格式 Marshal格式 Ruby FAQ Ruby的陷阱
characters

表達式(Expressions)



到目前為止我們已經(jīng)用了一些基本的表達式,畢竟,a=b+c是最基本的了,你即使不看本章,也能寫出一大堆的Ruby代碼來。但是那樣做不是什么有趣的事情;-)

Ruby和其它語言的一個不同之處就是任何東西都能返回一個值,幾乎所有的東西都是表達式,在實際中,這有什么意義呢?

一些明顯得作用是可以實現(xiàn)鏈?zhǔn)秸Z句:

a?=?b?=?c?=?0 ? 0
[?3,?1,?7,?0?].sort.reverse ? [7,?3,?1,?0]

一些不太起眼的東西,比如C和JAVA中的語句,在Ruby中都是表達式,例如,if和case都返回一個值,這個值就是這些語句中最后執(zhí)行的那行。

songType?=?if?song.mp3Type?==?MP3::Jazz
?????????????if?song.written?<?Date.new(1935,?1,?1)
???????????????Song::TradJazz
?????????????else
???????????????Song::Jazz
?????????????end
???????????else
?????????????Song::Other
???????????end



?rating?=?case?votesCast    
??????????when?0...10????then?Rating::SkipThisOne    
??????????when?10...50???then?Rating::CouldDoBetter    
??????????else????????????????Rating::Rave    
??????????end

操作表達式(Operator Expressions)

Ruby提供了諸如加減乘除等一些操作符,完整的操作符列表和優(yōu)先級在第18章有列表。

在Ruby中,很多操作符就是對一些方法的調(diào)用。比如你執(zhí)行a*b+c,實際上就是調(diào)用對象a的乘方法,把b作為一個參數(shù)傳遞過去,然后在調(diào)用這個結(jié)果對象的加方法,把c作為參數(shù)傳遞,實際上等于:

(a.*(b)).+(c)

因為你可以重新定義實例方法,所以你可以修改一些不能滿足你的需求的方法,讓它達到你需要的作用

class?Fixnum
??alias?oldPlus?+
??def?+(other)
????oldPlus(other).succ
??end
end
1?+?2 ? 4
a?=?3
a?+=?4 ? 8

很有用的一個技巧是你自己寫的的類可以像內(nèi)建對象一樣參與操作符的操作,比如,我們想從一首歌中間某處開始提取一部分音樂,我們可以用操作符"[ ]"來完成:

class?Song
??def?[](fromTime,?toTime)
????result?=?Song.new(self.title?+?"?[extract]",
??????????????????????self.artist,
??????????????????????toTime?-?fromTime)
????result.setStartTime(fromTime)
????result
??end
end

這段代碼擴展了類Song,增加了[ ]方法,這個方法接收兩個參數(shù),一個開始時間,一個結(jié)束時間。這個方法返回一個新的Song對象,這個對象是歌曲的一部分。然后,我們就可以這樣播放這段音樂:

aSong[0,?0.15].play

混合表達式(Miscellaneous Expressions)

除了上面最普通的操作符表達式,或者不是很顯眼的語句表達式(比如if或case),Ruby還支持在表達式中使用更多的東西。

命令展開 (Command Expansion)

如果你用反引號(`)來括起來一個字符串,或者用%x{ 和 }括起來,那么這個表達式中的字符串默認得會作為底層的操組系統(tǒng)命令來執(zhí)行,并返回結(jié)果,這個結(jié)果就是這個命令在操作系統(tǒng)中執(zhí)行之后的結(jié)果。換行符將不會從結(jié)果中去掉,所以返回結(jié)果一般都會包含一個回車符。

`date` ? "Sun?Jun??9?00:08:26?CDT?2002\n"
`dir`.split[34] ? "lib_singleton.tip"
%x{echo?"Hello?there"} ? "Hello?there\n"

你也可以在命令中使用表達式展開和所有通常的轉(zhuǎn)義序列。

for?i?in?0..3
??status?=?`dbmanager?status?id=#{i}`
??#?...
end

執(zhí)行的命令的返回狀態(tài)存放在全局變量$?中。

重載反引號方法

上面我們說道,反引號之中的命令"默認"會作為操作系統(tǒng)命令來執(zhí)行,實際上,這個字符串是傳遞給了 Kernel::` 這個方法(一個反引號)來執(zhí)行。如果你愿意,可以重寫這個方法,比如如下:

alias?oldBackquote?`
def?`(cmd)
??result?=?oldBackquote(cmd)
??if?$??!=?0
????raise?"Command?#{cmd}?failed"
??end
??result
end
print?`date`
print?`data`
產(chǎn)生:
Sun?Jun??9?00:08:26?CDT?2002
prog.rb:3:?command?not?found:?data
prog.rb:5:in?``':?Command?data?failed?(RuntimeError)
	from?prog.rb:10

賦值

我們前面的例子中都涉及到了賦值這一基本表達式,下面,我們來討論一些關(guān)于賦值語句的東西。

一個賦值語句給一個變量或者屬性設(shè)定一個指定的值,變量或?qū)傩栽谧筮叄翟谟疫?。然后這個值作為表達式的返回值返回。也就是說,我們可以用鏈?zhǔn)劫x值來給一些變量賦值:

a?=?b?=?1?+?2?+?3
a ? 6
b ? 6
a?=?(b?=?1?+?2)?+?3
a ? 6
b ? 3
File.open(name?=?gets.chomp)

在Ruby中有兩種基本的賦值格式,第一種是指給一個引用某一參數(shù)或者常量的對象賦值,這種形式是緊密連接到語言中的。

instrument?=?"piano"
MIDDLE_A???=?440

另一種是在賦值語句左邊使用對象的屬性或者元素的引用。

aSong.duration????=?234
instrument["ano"]?=?"ccolo"

這種方法比較特殊,通過調(diào)用左值的方法來賦值,也就是說我們可以重寫這些方法。

我們已經(jīng)看過如何定義一個可以修改的屬性了,只需要簡單的在方法后面以等號結(jié)尾即可。這個方法把接收的參數(shù)作為賦值語句的右值。

class?Song
??def?duration=(newDuration)
????@duration?=?newDuration
??end
end

沒有理由要求這些給參數(shù)設(shè)置值得方法與內(nèi)部的實例變量一致,或者每個可以修改的屬性都要提供一個讀方法,反過來也是一樣。

class?Amplifier
??def?volume=(newVolume)
????self.leftChannel?=?self.rightChannel?=?newVolume
??end
??#?...
end

Sidebar:在類中使用訪問方法( Accessors)
上面的例子中為什么我們必須要寫 self.leftChannel 而不能省掉self呢?一般的,一個類中的方法可以直接調(diào)用同類或者父類中的其他方法(默認得接收者是self),但是,對于attribute writers來說這就不管用了,Ruby將把左面的名字作為一個本地變量,而不是一個對寫屬性方法的調(diào)用。

 

class?BrokenAmplifier
??attr_accessor?:leftChannel,?:rightChannel
??def?volume=(vol)
????leftChannel?=?self.rightChannel?=?vol
??end
end
ba?=?BrokenAmplifier.new
ba.leftChannel?=?ba.rightChannel?=?99
ba.volume?=?5
ba.leftChannel ? 99
ba.rightChannel ? 5

我們在leftChannel前面忘了寫self.了,所以ruby把這個新值賦給了一個方法volume=的一個局部變量,而這個對象的屬性沒有任何變化。這可能會經(jīng)常產(chǎn)生問題。

并行賦值

在學(xué)習(xí)了一段時間程序設(shè)計之后,我們可能會遇到要求將兩個變量的值互換:

int?a?=?1;
int?b?=?2;
int?temp;
temp?=?a; a?=?b; b?=?temp;

在Ruby中很簡單,只需要:

a,?b?=?b,?a

Ruby可以有效的實現(xiàn)并行賦值,在右邊的值在被賦給左面的變量或?qū)傩灾鞍凑账鼈兊捻樣嵾M行求值,然后對應(yīng)的賦給左面的屬性或變量。一個例子如下,第二行給a,b,c的值分別是x,x+=1,x+=1計算之后的值。

x?=?0 ? 0
a,?b,?c???=???x,?(x?+=?1),?(x?+=?1) ? [0,?1,?2]

當(dāng)一個賦值語句左值多余一時,這個表達式的返回值是一個由右面的值組成的數(shù)組,如果一個賦值語句的左值多余右值,多余的左值被設(shè)為nil,反過來如果右值多余左值,那么多余的右值將被忽略。在Ruby1.6.2中,如果左值只有一個,右值有多個,那么這些右值將作為一個數(shù)組賦給左值。

你也可以在并行賦值語句中分解和擴展數(shù)組。如果最后的左值以星號作為前綴,那么所有對應(yīng)這個得值和以后的值將會組成一個數(shù)組,賦給這個左值(如下面第三行的c);類似的,如果最后一個右值是一個數(shù)組,你可以加一個星號作為前綴,Ruby將會把這個數(shù)組拆開按相應(yīng)的位置賦給左值(如下面第六行的c,而且,如果這個數(shù)組是唯一的右值,這個星號是可以省略的,作為右值得數(shù)組自動拆開,如第二行所示)。

a = [1, 2, 3, 4]
b,??c?=?a ? b == 1, c == 2
b,?*c?=?a ? b == 1, c == [2, 3, 4]
b,??c?=?99,??a ? b == 99, c == [1, 2, 3, 4]
b,?*c?=?99,??a ? b == 99, c == [[1, 2, 3, 4]]
b,??c?=?99,?*a ? b == 99, c == 1
b,?*c?=?99,?*a ? b == 99, c == [1, 2, 3, 4]

嵌套賦值

并行賦值還有一個值得一提的特性,賦值語句左邊還可以包括用括號括起來的變量列表,Ruby中叫做嵌套賦值語句。Ruby首先摘出右值中相應(yīng)的項進行賦值,然后在進行高層的賦值操作。

b,?(c,?d),?e?=?1,2,3,4 ? b == 1, c == 2, d == nil, e == 3
b,?(c,?d),?e?=?[1,2,3,4] ? b == 1, c == 2, d == nil, e == 3
b,?(c,?d),?e?=?1,[2,3],4 ? b == 1, c == 2, d == 3, e == 4
b,?(c,?d),?e?=?1,[2,3,4],5 ? b == 1, c == 2, d == 3, e == 5
b,?(c,*d),?e?=?1,[2,3,4],5 ? b == 1, c == 2, d == [3, 4], e == 5

其它賦值形式

像其它語言一樣,ruby也為a=a+2提供了類似a+=2的快捷方式。

第二種方式是第一種的深入,可以讓操作符當(dāng)成方法來工作。

class?Bowdlerize
??def?initialize(aString)
????@value?=?aString.gsub(/[aeiou]/,?'*')
??end
??def?+(other)
????Bowdlerize.new(self.to_s?+?other.to_s)
??end
??def?to_s
????@value
??end
end
a?=?Bowdlerize.new("damn?") ? d*mn
a?+=?"shame" ? d*mn?sh*m*

條件執(zhí)行(Conditional Execution)

Ruby有幾種不同的機制來實現(xiàn)條件執(zhí)行,大多數(shù)都感覺很類似,也有一些很靈巧,在深入討論之前,我們先來花點時間看看布爾表達式。

Boolean 表達式

Ruby中的true定義很簡單,任何不是nil和false常量的東西都是true,你會發(fā)現(xiàn)系統(tǒng)的實現(xiàn)庫中很多這種用法。比如, IO#gets ,用來返回一個文件的下一行,如果到了文件末尾,返回nil,所以,我們才可以這樣通過while來循環(huán)讀取數(shù)據(jù):

while?line?=?gets
??#?process?line
end

但是,這里對于c和perl程序員來說有一個誤區(qū),數(shù)字0和長度為0的字符串都不會被解釋成false值,需要注意。

Defined?, And, Or, 和 Not

Ruby支持所有標(biāo)準(zhǔn)的布爾操作,另外,還引入了新的操作符defined?

操作符``and'' 和``&&'' 只有當(dāng)兩面的值都為真才會返回真,第一個值為真,才會判斷第二個值,否則直接返回假。這兩個操作符的區(qū)別是優(yōu)先級不同(and低于 &&)

類似的 ``or'' 和``||''有一方為真就會返回真,如果第一個為真,則不會判斷后面的值,類似and,這兩個操作符只有優(yōu)先級的不同。

and和or有相同的優(yōu)先級,而&&的優(yōu)先級高于||。

?

``not'' and ``!'' 返回操作數(shù)的相反的值,如果操作數(shù)為true,則這個操作符返回false。并且and和!也只是優(yōu)先級不同。

所有的這些操作符和優(yōu)先級都在18章有詳細講述。

操作符defined?將返回nil,如果操作數(shù)沒有定義的話。否則,將返回后面參數(shù)的描述信息。

?

defined??1 ? "expression"
defined??dummy ? nil
defined??printf ? "method"
defined??String ? "constant"
defined??$& ? nil
defined??$_ ? "global-variable"
defined??Math::PI ? "constant"
defined??(?c,d?=?1,2?) ? "assignment"
defined??42.abs ? "method"

除了這些布爾表達式,Ruby對象還支持使用 ==, ===, <=>, =~, eql?, 和equal?進行對象之間的比較。除了<=>之外這些操作符都在Object類中定義,但是經(jīng)常被子類重載。比如,類Array重定義了==方法,判斷兩個數(shù)組相同的條件事它們的個數(shù)相同,同一位置的元素也相同。

通用比較操作符
操作符 意義
== 測試是否相同
=== 在case中的when語句判斷是否相等
<=> 通用比較操作符,根據(jù)前面的對象小于,等于還是大于后面的對象,返回 -1, 0, 或者 +1。
<, <=, >=, > 小于,小于等于,大于等于,大于
=~ 正則表達式匹配
eql? 如果前后兩個對象都是同一類型,則返回true: 1 == 1.0返回true但是 1.eql?(1.0) 結(jié)果為false。
equal? 只有兩個對象有相同的object id 才返回true。

==和=~都有相反的操作符!=和!~,但是Ruby會將程序中的a!=b轉(zhuǎn)換為!(a==b),a!~b轉(zhuǎn)換成!(a=~b),如果你自己的類中重新寫了==和=~方法,那么你同時的到了!=和!~兩個方法;同時,你也不能離開了==和=~而孤立的定義!=和!~兩個方法。

你可以使用Ruby? range 作為一個布爾表達式,一個類似 exp1..exp2 的range只有在遇到exp1為true,然后exp2又為true之后,才會返回true。下面循環(huán)部分有例子。

最后,你可以用正則表達式來當(dāng)作一個布爾表達式。Ruby expands it to $_=~/re/.

If 和 Unless表達式

Ruby中的if語句跟其他語言類似。

if?aSong.artist?==?"Gillespie"?then
??handle?=?"Dizzy"
elsif?aSong.artist?==?"Parker"?then
??handle?=?"Bird"
else
??handle?=?"unknown"
end

如果你的if語句寫在多行上,可以省略then關(guān)鍵字。

if?aSong.artist?==?"Gillespie"
??handle?=?"Dizzy"
elsif?aSong.artist?==?"Parker"
??handle?=?"Bird"
else
??handle?=?"unknown"
end

但是,如果你的語句都寫在一行上,then應(yīng)該寫上來分開布爾表達式和后面的語句。

if?aSong.artist?==?"Gillespie"?then??handle?=?"Dizzy"
elsif?aSong.artist?==?"Parker"?then??handle?=?"Bird"
else??handle?=?"unknown"
end

你可以使用0個或多個elsif語句,和一個可選的else語句。

就像我們前面說道的,if是一個表達式,不是一個statement,它可以返回一個值,你不必使用if表達式的返回值,但是它可能有些用處。

handle?=?if?aSong.artist?==?"Gillespie"?then
???????????"Dizzy"
?????????elsif?aSong.artist?==?"Parker"?then
???????????"Bird"
?????????else
???????????"unknown"
?????????end

Ruby也未if提供了一個否定的形式,unless:

unless?aSong.duration?>?180?then
??cost?=?.25
else
??cost?=?.35
end

最后,也為使用C語言的程序員準(zhǔn)備了條件表達式:

cost?=?aSong.duration?>?180???.35?:?.25

這個條件表達式在根據(jù)?前面的布爾值為true或false返回冒號前面或后面的值。在這個例子中,如果歌曲的時長大于3分鐘,將返回.35,否則返回.25,然后,將這個值賦給cost。

If 和 Unless 修飾符(Modifiers)

Ruby也借鑒了Perl的一些特點,語句修飾符(Statement modifiers)使我們可以在語句末尾加上條件語句。

mon,?day,?year?=?$1,?$2,?$3?if?/(\d\d)-(\d\d)-(\d\d)/
puts?"a?=?#{a}"?if?fDebug
print?total?unless?total?==?0

對于if修飾符來說,只有當(dāng)if后面的條件為true,前面的語句才會執(zhí)行,unless正好和if相反。

while?gets
??next?if?/^#/????????????#?Skip?comments
??parseLine?unless?/^$/???#?Don't?parse?empty?lines
end

因為if本身也是表達式,所以下面的寫法將會使代碼變得難懂。

if?artist?==?"John?Coltrane"
??artist?=?"'Trane"
end?unless?nicknames?==?"no"

 

Case 表達式

Ruby的 case 表達式非常強大,就像多個if的固化物一樣。

case?inputLine



??when?"debug"          
????dumpDebugInfo          
????dumpSymbols


??when?/p\s+(\w+)/           
????dumpVariable($1)

??when?"quit",?"exit"           
????exit

??else           
????print?"Illegal?command:?#{inputLine}"           
end 

像if一樣,case返回最后執(zhí)行的語句的結(jié)果,如果你的when和后面的語句都在一行,你也需要加一個then關(guān)鍵字。

kind?=?case?year
?????????when?1850..1889?then?"Blues"
?????????when?1890..1909?then?"Ragtime"
?????????when?1910..1929?then?"New?Orleans?Jazz"
?????????when?1930..1939?then?"Swing"
?????????when?1940..1950?then?"Bebop"
?????????else?????????????????"Jazz"
???????end

case 操作符根據(jù)case后面目標(biāo)的值,跟每個when后面的值用===進行判斷,

operates by comparing the target (the expression after the keyword case) with each of the comparison expressions after the when keywords. This test is done using comparison?===?target. As long as a class defines meaningful semantics for === (and all the built-in classes do), objects of that class can be used in case expressions.

For example, regular expressions define === as a simple pattern match.

case?line
??when?/title=(.*)/
????puts?"Title?is?#$1"
??when?/track=(.*)/
????puts?"Track?is?#$1"
??when?/artist=(.*)/
????puts?"Artist?is?#$1"
end

Ruby classes are instances of class Class, which defines === as a test to see if the argument is an instance of the class or one of its superclasses. So (abandoning the benefits of polymorphism and bringing the gods of refactoring down around your ears), you can test the class of objects:

case?shape
??when?Square,?Rectangle
????#?...
??when?Circle
????#?...
??when?Triangle
????#?...
??else
????#?...
end

循環(huán)

不要告訴他人,Ruby支持原始的靈巧的內(nèi)建循環(huán)結(jié)構(gòu)。

while循環(huán)根據(jù)它的條件的真假來執(zhí)行0次或者多次語句,比如,下面程序?qū)⒁恢边\行,直到輸入被打斷。

while?gets
??#?...
end

util也可以用來循環(huán),知道條件為真,才停止操作。

until?playList.duration?>?60
??playList.add(songList.pop)
end

像if和unless一樣,while和until也可以用作語句操作符。

a?*=?2?while?a?<?100
a?-=?10?until?a?<?100

在前面的布爾表達式中,我們說過range也可以作為布爾表達式,這個機制多用于循環(huán)中,在下面的例子中,我們從一個包含從first到tenth的數(shù)字的文本文件中讀取數(shù)據(jù),但是只打印從以third開頭的行,直到遇到fifth開頭的行為止。

file?=?File.open("ordinal")
while?file.gets
??print??if?/third/?..?/fifth/
end
打印結(jié)果:
third
fourth
fifth

The elements of a range used in a boolean expression can themselves be expressions. These are evaluated each time the overall boolean expression is evaluated. For example, the following code uses the fact that the variable $. contains the current input line number to display line numbers one through three and those between a match of /eig/ and /nin/.

file?=?File.open("ordinal")
while?file.gets
??print?if?($.?==?1)?||?/eig/?..?($.?==?3)?||?/nin/
end
produces:
first
second
third
eighth
ninth

這里有一點需要注意,當(dāng)while和until用作語句修飾符的時候,如果它們修飾的語句以begin開頭,end結(jié)尾,這段代碼將總會執(zhí)行,而不管后面的條件。

print?"Hello\n"?while?false
begin
??print?"Goodbye\n"
end?while?false
produces:
Goodbye

迭代Iterators

上面我們知道了,Ruby支持簡單的循環(huán),比如,Ruby沒有for循環(huán),而c和JAV等都支持for循環(huán)的,但是Ruby提供了其他的機制,比如迭代,提供了類似的功能。

讓我們看看一個例子:

3.times?do
??print?"Ho!?"
end
produces:
Ho!?Ho!?Ho!

這可以避免off-by-1 錯誤,這個循環(huán)將執(zhí)行3次。除了times,整數(shù)還可以接收一些方法來執(zhí)行循環(huán),比如downto,upto,和step等。比如,傳統(tǒng)的從0到9的循環(huán)(類似for( i=0; i < 10; i++)) 類似下面的樣子:

0.upto(9)?do?|x|
??print?x,?"?"
end
produces:
0?1?2?3?4?5?6?7?8?9

一個從0到12,步長為3的循環(huán)如下:

0.step(12,?3)?{|x|?print?x,?"?"?}
produces:
0?3?6?9?12

用于數(shù)組和其它容器的迭代的each方法也可以用來循環(huán)。

[?1,?1,?2,?3,?5?].each?{|val|?print?val,?"?"?}
produces:
1?1?2?3?5

如果一個類支持了each方法,那么在模塊Enumerable 中的方法也可以直接使用。比如,F(xiàn)ile類提供了each方法,依次返回一個文件的每一行。使用Enumerable中的grep方法,我們可以只迭代符合條件的行。

File.open("ordinal").grep?/d$/?do?|line|
??print?line
end
produces:
second
third

最后也是最簡單的,Ruby提供了一個內(nèi)建的最基本的迭代器loop。

loop?{
??#?block?...
}

loop迭代器一直調(diào)用給定的block(或者你調(diào)用了break跳出循環(huán),后面會講到)。

For ... In

前面我們說道Ruby支持的最基本循環(huán)視while和until,而for指的什么呢,可以看如下代碼:

for?aSong?in?songList
??aSong.play
end

Ruby將會把它翻譯為如下:

songList.each?do?|aSong|
??aSong.play
end

for和each的唯一區(qū)別是局部變量的作用域。

你可以在支持each的類上使用for方法,比如Array或者Range。

for?i?in?['fee',?'fi',?'fo',?'fum']
??print?i,?"?"
end
for?i?in?1..3
??print?i,?"?"
end
for?i?in?File.open("ordinal").find_all?{?|l|?l?=~?/d$/}
??print?i.chomp,?"?"
end
produces:
fee?fi?fo?fum?1?2?3?second?third

一旦你的類支持了each方法,你就可以使用for來進行遍歷。

class?Periods
??def?each
????yield?"Classical"
????yield?"Jazz"
????yield?"Rock"
??end
end
 
periods?=?Periods.new             
for?genre?in?periods             
??print?genre,?"?"             
end
 
produces:
Classical?Jazz?Rock

Break, Redo, 和 Next

循環(huán)控制結(jié)構(gòu) break, redo, 和 next 讓你可以控制循環(huán)或者迭代器的流程。

break 立即結(jié)束當(dāng)前循環(huán),然后跳出去執(zhí)行循環(huán)后面的語句。redo從這次循環(huán)體的頭開始重新執(zhí)行,但是不會在對條件進行運算或者從迭代中取下一個值。next跳到本次循環(huán)末尾,開始執(zhí)行下一次循環(huán)。

while?gets
??next?if?/^\s*#/???#?skip?comments
??break?if?/^END/???#?stop?at?end
????????????????????#?substitute?stuff?in?backticks?and?try?again
??redo?if?gsub!(/`(.*?)`/)?{?eval($1)?}
??#?process?line?...
end

這些關(guān)鍵字也可以用在基于迭代器的循環(huán)機制中。

i=0
loop?do
??i?+=?1
??next?if?i?<?3
??print?i
??break?if?i?>?4
end
produces:
345

Retry

redo使一個循環(huán)從當(dāng)前迭代中重新執(zhí)行。有時候,你需要從新開始一個循環(huán),retry從新開始任何地迭代循環(huán)。

for?i?in?1..100
??print?"Now?at?#{i}.?Restart??"
??retry?if?gets?=~?/^y/i
end

運行上面的程序,結(jié)果如下:

Now?at?1.?Restart??n
Now?at?2.?Restart??y
Now?at?1.?Restart??n
?.?.?.

retry 將重新計算條件值,然后再開始循環(huán)。Ruby文檔有如下例子:

def?doUntil(cond)
??yield
??retry?unless?cond
end

 
i?=?0              
doUntil(i?>?3)?{              
??print?i,?"?"              
??i?+=?1              
}
produces:
0?1?2?3?4

變量作用域和循環(huán)

while,until和for循環(huán)內(nèi)建于Ruby語言之中,沒有引入新的作用域,前面定義的局部變量可以在循環(huán)中使用,在循環(huán)中創(chuàng)建的變量在后面的代碼也可以使用。

而對loop或each使用block來說則不一樣了。在這個block中創(chuàng)建的變量在外面是不能訪問的。

[?1,?2,?3?].each?do?|x|
??y?=?x?+?1
end
[?x,?y?]
produces:
prog.rb:4: undefined local variable or method `x'
for #<Object:0x401c2ce0> (NameError)

然而,如果block中的變量和前面已經(jīng)定義的變量重名的話,已經(jīng)存在的變量將會在塊中使用,而在塊執(zhí)行完成后,這個變量的值也會改變。下面的例子,我們看到block執(zhí)行之后,兩個變量都改變了。

x?=?nil
y?=?nil
[?1,?2,?3?].each?do?|x|
??y?=?x?+?1
end
[?x,?y?] ? [3,?4]


Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright ? 2001 by Addison Wesley Longman, Inc. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/)).

Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.

Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
Previous article: Next article: