Day8 讀書筆記&心得體會(huì)

一绵载、心得體會(huì)

今天完成了什么

  • 看了20頁的鎬頭書
  • 學(xué)了bag的10個(gè)controller

收獲什么饲梭?

  • 新增期吓、編輯都放在show視圖里
  • 活動(dòng)平臺(tái)
  • 訂單活動(dòng)
  • 地址早歇、地址快照、品牌

二讨勤、讀書筆記
回顧昨天學(xué)到內(nèi)容

  • 肯定匹配 =~
    舉個(gè)栗子:
name = "ni shi da sha gua"
name =~ /a/   -> 8

匹配操作符返回匹配發(fā)生的字符位置箭跳,它們也有副作用,會(huì)設(shè)置一些Ruby變量潭千?谱姓??

$`得到匹配之前的那部分字符串刨晴,$'得到匹配之后的那部分字符串屉来。

所以,可以這么寫show_regexp方法狈癞,以說明具體的模式在何處發(fā)生匹配茄靠。

舉個(gè)栗子:

def show_regexp(a, re)
  if a =~ re
    "#{$` } <<#{$&}>>#{$' }"
  else
    "no match"
  end
end
show_regexp('very interesting', /t/) -> very in <<t>>eresting

這個(gè)匹配也設(shè)置了線程局部變量(thread-local variables)?亿驾?嘹黔?,$~與$1直到$9莫瞬。

$~變量是MatchData對象儡蔓,它持有你想知道的有關(guān)匹配的所有信息。???

$1等持有匹配各個(gè)部分的值疼邀,我們在后面會(huì)談到這些喂江。對那些看到類似Perl變量名就心懷畏懼的人來講,請稍安勿躁得啦旁振!

關(guān)于模式

每個(gè)正則表達(dá)式包含一種模式获询,用來對字符串進(jìn)行正則表達(dá)式的匹配涨岁。

在模式內(nèi),除了.吉嚣,|梢薪,(,)尝哆,[秉撇,],{秋泄,}琐馆,+,\恒序,^瘦麸,$,*和?字符之外歧胁,所有字符串匹配它們本身滋饲。

注意:在這些特殊字符之前放置一個(gè)反斜線便可以匹配它們的字面量。舉個(gè)栗子:

show_regexp("yes | no", /\|/) -> yes <<|>> no

如果不加反斜線的話:

show_regexp("yes | no", /|/) -> <<>>yes | no

返回的竟然是:

<<>>yes | no

為什么會(huì)這樣呢与帆?
這是因?yàn)閨是特別字符了赌,未轉(zhuǎn)義的豎線要么匹配在它之前的正則表達(dá)式,要么匹配在它之后的正則表達(dá)式玄糟。
這里的豎線(|)前后都是空,所以匹配的也是空袄秩,匹配的順序是從左到右阵翎,所以就是上面那個(gè)樣子。

但是之剧,有些同學(xué)會(huì)疑惑郭卫,那到底是先匹配模式中豎線(|)的左邊還是豎線的右邊呢?讓我們來做個(gè)對照試驗(yàn)背稼。
舉個(gè)栗子:

show_regexp(" red ball blue sky", /red|/) -> <<red>> ball blue sky
show_regexp("red ball blue sky", /|red/) -> <<>>red ball blue sky

red放在左邊的時(shí)候贰军,能匹配出字符串中的red
而red放在右邊的時(shí)候,則不能匹配出字符串的red蟹肘,反而匹配的是空词疼。
這說明,前者在匹配的時(shí)候帘腹,是從模式中豎線的左邊和字符串中的最左邊的空開始匹配贰盗。

show_regexp("red ball blue sky", /red|blue/)  -> <<red>> ball blue sky
show_regexp("red ball blue sky", /blue|red/)  -> <<red>> ball blue sky

show_regexp("blue ball red sky", /red|blue/)  -> <<blue>> ball red sky
show_regexp("blue ball red sky", /blue|red/)  -> <<blue>> ball red sky

從上面的例子中,我們可以發(fā)現(xiàn)阳欲,無論匹配模式里的red和blue放在哪邊舵盈,結(jié)果都是一樣的陋率,所以。

但是秽晚,如果把匹配字符串里的blue和red交換位置瓦糟,我們會(huì)發(fā)現(xiàn),匹配出來的不是red赴蝇,竟然是blue狸页。

所以,無論是先匹配模式中豎線的左邊還是右邊扯再,都不會(huì)影響結(jié)果芍耘。

5.4.2基于模式的替換(Pattern-Based Substitution)

在字符串中能夠發(fā)現(xiàn)模式有時(shí)就已經(jīng)足夠好了,如果你的朋友給出難題熄阻,讓你找出順序包含字母a斋竞,b,c秃殉,d和e的詞坝初,你可能會(huì)使用模式/a.b.cd.e/去查找詞表并找出abjectedness,absconded钾军,ambuscade和carbacidometer這些詞等等鳄袍,這種事情肯定有價(jià)值的。

當(dāng)然吏恭,有時(shí)候待根據(jù)模式匹配去改變一些東西拗小,讓我們回到歌曲列表文件中,不管是誰樱哼,都會(huì)以小寫方式輸入歌曲演唱者的名字哀九,以混合大小寫方式在點(diǎn)唱機(jī)的屏幕上顯示它們會(huì)更好看,怎么樣才能把每個(gè)詞的首字符改成大寫呢搅幅?

String#sub和String#gsub方法超找出能夠匹配第一個(gè)參數(shù)的那部分字符串阅束,同時(shí)用第二個(gè)參數(shù)替換這它們。String#sub執(zhí)行一次替換茄唐,而String#gsub在匹配每次出現(xiàn)都進(jìn)行替換息裸。

兩個(gè)方法都返回了對含有這些替換字符串的新的拷貝。Mutator版本的String#sub沪编!和String#gsub!會(huì)直接修改原先的字符串呼盆。

a = "the quick brown fox"
a.sub(/[aeiou]/, '*')
a.gsub(/[aeiou]/, '*')
a.sub(/\s\S+/, '')
a.gsub(/\s\S+/, '')

兩個(gè)函數(shù)的第二個(gè)參數(shù)可以是String或block。如果使用block漾抬,匹配的字符串會(huì)被傳遞被block宿亡,同時(shí)block的結(jié)果值會(huì)被替換到原先的字符串中。

a = "the quick brown fox"
a.sub(/^./){|match| match.upcase}
a.gsub(/[aeiou]/) {|vowel| vowel.upcase}

所以纳令,對如何轉(zhuǎn)換歌曲演唱者名字的這個(gè)問題挽荠,我們給出了大難克胳。匹配詞的首字符的模式是\b\w——它尋找后面跟著詞字符(word character)的詞邊界。把這個(gè)模式和gsub結(jié)合起來圈匆,可以改變歌曲演唱者的名字了漠另。

def mixed_case(name)
  name.gsub(/\b\w/) {|first| first.upcase}
end
mixed_case("fats waller")
mixed_case("louis armstrong")
mixed_case("strength in numbers")

替換中的反斜線序列

早些時(shí)候我們注意到序列\(zhòng)1和\2等在模式中可用,它們代表至今為止第n個(gè)已匹配的組跃赚,相同的序列也可以作為sub和gsub的第二個(gè)參數(shù)笆搓。

"fred:smith".sub(/(\w+):(\w+)/, '\2, \1')
"nercpyitno".gsub(/(.)(.)/, '\2\1')

其他的反斜線序列在替換字符串中起的作用:&(最后的匹配),+(最后匹配的組)纬傲,'(匹配之前的字符串)满败,'(匹配之后的字符串)和\(字面量反斜線)。

如果想在替換中包含字面量反斜線叹括,我們會(huì)變得很困惑算墨,顯然可以寫成:

str.gsub(/\\/, '\\\\')

很清楚,代碼正試圖用兩個(gè)反斜線替換str中的每個(gè)反斜線汁雷,程序員在替換文本中用了雙倍的反斜線净嘀,因?yàn)橹浪鼈冊谡Z法分析階段中會(huì)被轉(zhuǎn)化成\。但是當(dāng)替換發(fā)生時(shí)侠讯,正則表達(dá)式引擎對字符串又執(zhí)行了一遍挖藏,并把\轉(zhuǎn)換成\,所以最終結(jié)果是使用另外一個(gè)反斜線替換每個(gè)反斜線厢漩。需要把它寫成gsub(/\/, '\\\\')!
str = 'a\b\c'
str.gsub(/\/, '\\\\')
但是膜眠,如果利用&被替換為已匹配的字符串這個(gè)事實(shí),也可以寫成:
str = 'a\b\c'
str.gsub(/\/, '&&')

如果使用gsub的block形式袁翁,用來替換的字符串會(huì)被和僅被分析一次(在語法分析階段)柴底,這正是所希望看到的結(jié)果。

str = 'a\b\c'
str.gsub(/\/) { '\\' }
最后粱胜,下面的例子極好的表達(dá)了結(jié)合使用正則表達(dá)式和block,請參見由Wakou A編寫的CGI庫模塊的代碼片段狐树,這段代碼接受包含HTML轉(zhuǎn)義序列的字符串并把它轉(zhuǎn)換成普通的ASCII焙压。

為了支持日本用戶,它在正則表達(dá)式上使用了n修飾符關(guān)閉了寬字符處理抑钟,它也說明了Ruby的case表達(dá)式涯曲。

def unescapeHTML(string) 
  str = string.dup
  str.gsub!(/&(.*?); /n) {
    match = $1.dup
    case match
    when /\Aamp\z/ni  then '&'
    when /\Aquot\z/ni then  '*'
    when /\Agt\z/ni     then '>'
    when /\Alt\z/ni       then '<'
    when /\A#(\d+)\z\/n then Integer($1).chr
    when /\A#x([0-9a-f]+)\z/ni  then $1.hex.chr
    end
  }
  str
end

puts unescapeHTML("1<2 & 4>3")
puts unescapeHTML(""A" = A = A")

輸出結(jié)果:
1<2 && 4>3
"A" = A = A

dup:復(fù)制對象沒有分配ID,并被視為新記錄在塔。請注意幻件,這是一個(gè)“淺”副本,因?yàn)樗鼉H復(fù)制對象的屬性蛔溃,而不是其關(guān)聯(lián)绰沥。 “深”副本的范圍是特定于應(yīng)用程序的篱蝇,因此由應(yīng)用程序根據(jù)需要進(jìn)行實(shí)施。 dup方法不保留時(shí)間戳(已創(chuàng)建|更新)_(at | on)徽曲。

5.4.3面向?qū)ο蟮恼齽t表達(dá)式(Object-Oritended Regular Expressions)

必須承認(rèn)零截,盡管所有這些古怪的變量用起來十分方便,但是它們不是面向?qū)ο蟮耐撼迹瑫r(shí)它們很神秘涧衙,難道我們沒有說Ruby的所有物體都是對象嗎?哪里出錯(cuò)了奥此?

真的沒有錯(cuò)弧哎,在Matz設(shè)計(jì)Ruby時(shí),他設(shè)計(jì)了一個(gè)完全面向?qū)ο蟮恼齽t表達(dá)處理系統(tǒng)稚虎,然后在它之上包裝(wrap)所有這些$變量撤嫩,使它們看起來對Perl程序員很熟悉。對象和類還在這里祥绞,只不過就在表面下非洲,讓我們花點(diǎn)時(shí)間把它們挖掘出來吧。

實(shí)際上已經(jīng)遇到一個(gè)類:正則表達(dá)式字面量創(chuàng)建了Regexp類的實(shí)例蜕径。

re = /cat/
re.class -> Regexp

Regexp#match方法對字符串匹配正則表達(dá)式两踏。如果失敗了,它返回nil兜喻。如果成功梦染,則返回MatchData類的一個(gè)實(shí)例。MatchData對象讓你訪問關(guān)于這次匹配的所有可用信息朴皆,所有這些好東西通過$變量得到的帕识,它們綁定在一個(gè)小巧方便的對象。

re = /(\d+):(\d+)/ # match a time hh:mm
md = re.match("Time: 12:34am")
md.class 
md[0] # == $&
md[1] # == $1
md[2] # == $2
md.pre_match # == $`
md.post_match # == $'

匹配數(shù)據(jù)存儲(chǔ)在它自己的對象里遂铡,這樣可以同時(shí)保留兩個(gè)或多個(gè)模式匹配的結(jié)果肮疗,這些事情使用那些$變量是做不出來的。在下面的例子中扒接,對兩個(gè)字符串匹配相同的Regexp對象伪货,每次匹配返回唯一的MatchData對象,通過檢驗(yàn)兩個(gè)子模式字段來驗(yàn)證它钾怔。

re = /(\d+):(\d+)/
md1 = re.match("Time: 12:34am")
md2 = re.match("Time: 10:30pm")
md1[1, 2]

第6章

關(guān)于方法的更多細(xì)節(jié)(more about Methods)

6.1 定義一個(gè)方法

  • 以小寫字母開頭

如果你使用大寫字符碱呼,并不會(huì)立即得到一個(gè)錯(cuò)誤,但是當(dāng)Ruby看到你調(diào)用這個(gè)方法時(shí)宗侦,它首先猜測這是一個(gè)常量愚臀,而不是一個(gè)方法調(diào)用,且結(jié)果是Ruby可能錯(cuò)誤地解析這個(gè)調(diào)用矾利。

  • 表示查詢的方法名通常以?結(jié)尾姑裂,例如instance_of馋袜?
  • “危險(xiǎn)的”或者會(huì)修改接收對象(receiver)的方法,可以用!結(jié)尾炭分,例如String提供了chop和chop!方法桃焕,第一個(gè)返回一個(gè)修改后的字符串;第二個(gè)則就地修改對象捧毛。

舉個(gè)栗子:

我們已經(jīng)新方法指定了一個(gè)名字观堂,可能還需要聲明某些參數(shù)(parameter,形參)呀忧,它們就是括號(hào)中列出的局部變量师痕。(方法參數(shù)兩邊的括號(hào)是可選的;我們的慣例是而账,當(dāng)方法有參數(shù)時(shí)則使用括號(hào)胰坟,否則忽略它們。)

def my_new_method(arg1, arg2, arg3)
  #Code for the method would go there
end

Ruby可以讓你指定方法參數(shù)(argument泞辐,實(shí)參)的默認(rèn)值——如果調(diào)用者在傳入?yún)?shù)時(shí)沒有明確指定所使用的的值笔横。為此你可以使用賦值操作符。

def cool_dude(arg1="Miles", arg2="Coltrane", arg3="Roach")
    "#{arg1}, #{arg2}, #{arg3}."
end

方法體內(nèi)是普通的Ruby表達(dá)式咐吼,你不能在方法內(nèi)定義非單件(nonsingleto)類或模塊吹缔。如果你在一個(gè)方法內(nèi)定義另一個(gè)方法,內(nèi)部的方法只有在外部執(zhí)行時(shí)才得到定義锯茄,方法的返回值是執(zhí)行的最后一個(gè)表達(dá)式的值厢塘,或者return表達(dá)式顯示返回的值。

6.1.1 可變長度的參數(shù)列表(Variable-Length Argument Lists)

但是如果你希望傳入可變個(gè)數(shù)的參數(shù)(argument)肌幽、或者想用一個(gè)形參(parameter)接收多個(gè)參數(shù)晚碾,在“普通”的參數(shù)名前放置一個(gè)星號(hào)(*)即可。

def varargs(arg1, *rest)
  "Got #{arg1} and #{rest.join(', ')}"
end
varargs("one")
varargs("one", "two")

在這個(gè)栗子中喂急,和往常一樣第一個(gè)參數(shù)賦值給方法的第一個(gè)形參格嘁,不過,第二個(gè)形參的前綴為星號(hào)廊移,因此所有剩余的參數(shù)被裝入到一個(gè)新的Array中讥蔽,然后賦值給第二個(gè)形參。

6.1.2 方法和Block(methods and Blocks)

之前講過“Block和迭代器“画机,調(diào)用一個(gè)方法是,可以用一個(gè)block與之相關(guān)聯(lián)新症,通常步氏,您可以使用yield從方法內(nèi)部調(diào)用這個(gè)block。

def take_block(p1)
  if block_given?
    yield(p1)
  else
    p1
  end
end

take_block("no block")
take_block("no block") {|s| s.sub(/no /, '')}

不過如果方法定義的最后一個(gè)參數(shù)前綴為&徒爹,那么所關(guān)聯(lián)的block會(huì)被轉(zhuǎn)換為一個(gè)Proc對象荚醒,然后賦值給這個(gè)參數(shù)芋类。

class TaxCalculator
  def initialize(name, &block)
    @name, @block = name, block
  end
  def get_tax(amount)
    "#@name on #{amount} = #{ @block.call(amount) }"
  end
end
tc = TaxCalculator.new("Sales tax") { |amt| amt * 0.075 } 
tc.get_tax(100)

調(diào)用方法(Calling a Method)

你可以通過指定接受者、方法的名稱界阁、可選的參數(shù)及block侯繁,來調(diào)用一個(gè)方法。

connection.download_MP3("jitterbug") {|p| show_progress(p)}

在這個(gè)栗子中泡躯,connection對象是接收者贮竟,download_MP3是方法的名稱,”jitterbug“是參數(shù)较剃,花括號(hào)中的內(nèi)容是相關(guān)聯(lián)的block咕别。

對類方法或者模塊來說,接收者是類或模塊的名字写穴。

File.size("testfile")
Math.sin(Math::PI/4)

如果你省略了接收者惰拱,其默認(rèn)為self,也就是當(dāng)前的對象啊送。

self.class
self.frozen

Ruby正是用這種默認(rèn)的機(jī)制實(shí)現(xiàn)私有方法調(diào)用的偿短,我們無法調(diào)用某個(gè)接受對象的私有方法,它們只是在當(dāng)前對象(self)中是可用的馋没。

而在前面的栗子中昔逗,我們調(diào)用self.class時(shí)必須要指定一個(gè)接收對象,這是因?yàn)閏lass在Ruby中是一個(gè)關(guān)鍵字(它引入類的定義)披泪,因此單獨(dú)使用它會(huì)產(chǎn)生語法錯(cuò)誤纤子。

可選的參數(shù)跟隨在方法名之后,如果沒有二義性款票,在調(diào)用方法時(shí)控硼,你可以省略參數(shù)列表兩側(cè)的括號(hào),不過艾少,除非最簡單的情況卡乾,我們不推薦這樣做——某些微妙的問題可能會(huì)讓你犯錯(cuò)誤,我們的規(guī)則很簡單:只要你有任何疑慮缚够,就使用括號(hào)幔妨。

a = obj.hash
a = obj.hash()
obj.some_method

6.2.1 方法返回值(Method Return Values)
每個(gè)被調(diào)用的方法都會(huì)返回一個(gè)值(盡管沒有規(guī)定說你必須要使用這個(gè)值)。方法的值谍椅,是在方法執(zhí)行中最后一個(gè)語句執(zhí)行的結(jié)果误堡,Ruby有一個(gè)return語句,可以從當(dāng)前的執(zhí)行的方法中退出雏吭,return的返回值是其參數(shù)的值锁施,如果不需要return就省略之,這是Ruby的一個(gè)慣用技法。

def meth_one
  "one"
end
meth_one
def meth_three
  100.times do |num|
    square = num*num
    return num, square if square >1000
  end
end

最后一種情況演示了悉抵,如果你給定return多個(gè)參數(shù)肩狂,方法會(huì)將它們以數(shù)組的形式返回。你可以使用并行賦值來收集返回值姥饰。

num, square = meth_three

在方法調(diào)用中的數(shù)組展開

我們最早看到傻谁,在方法定義中,如果你在一個(gè)正規(guī)參數(shù)前加一個(gè)星號(hào)列粪,那么傳入這個(gè)方法調(diào)用的多個(gè)參數(shù)將會(huì)被裝入一個(gè)數(shù)組中审磁,當(dāng)然,也有某些操作是相反的方式篱竭。

當(dāng)你調(diào)用一個(gè)方法時(shí)力图,你可以分解一個(gè)數(shù)組,這樣每個(gè)成員都視為單獨(dú)的參數(shù)掺逼。在數(shù)組參數(shù)(必須在所有普通參數(shù)的后面)前加一個(gè)星號(hào)完成這一點(diǎn)吃媒。

def five(a, b, c, d, e)
  "I was passed #{a} # #{c} #rywwh7i #{e}"
end

five(1, 2, 3, 4, 5)

讓block更加動(dòng)態(tài)

我們已經(jīng)看到如何為方法調(diào)用關(guān)聯(lián)一個(gè)block吕喘。

list_bones("aardvark") do |bone|

...

end

一般來說赘那,這已經(jīng)足夠好了——你可以將一個(gè)固定的block關(guān)聯(lián)到方法,就如同在if或while語句之后編寫的一大塊代碼氯质。

但是募舟,某些時(shí)候,你希望更加靈活一些闻察,例如拱礁,我們希望教授一些算術(shù)技法,學(xué)生可能想要一個(gè)n次相加或相乘的表辕漂,如果學(xué)生需要一個(gè)2倍次的表呢灶,我們就輸出2,4钉嘹,6鸯乃,8等。

print "(t)imes or (p)lus:"
times = gets
print "number: "
number = Integer(gets)
if times =~ /^t/
  puts ((1..10).collect {|n| n*number}.join(",  "))
else
  puts ((1..10).collect {|n| n+number}.join(",  "))
end

這可以工作跋涣,不過在每個(gè)if語句之后重復(fù)實(shí)質(zhì)上等價(jià)的代碼缨睡,頗為丑陋,如果我們可以將完成計(jì)算的block抽取出來陈辱,代碼就漂亮富多了奖年。

print "(t)imes or (p)lus:"
times = gets
print "number: "
number = Integer(gets)
if times =~ /^t/
  puts (lambda{|n| n*number})
else
  puts (lambda {|n| n+number})
end

如果方法的最后一個(gè)參數(shù)前有&符號(hào),Ruby將認(rèn)為它是一個(gè)Proc對象沛贪,它會(huì)將其從參數(shù)列表中刪除拾并,并將Proc對象轉(zhuǎn)換為一個(gè)block揍堰,然后關(guān)聯(lián)到該方法。

收集散列參數(shù)

某些語言支持關(guān)鍵字參數(shù)——也就是你可以任意順序傳入?yún)?shù)的名稱與值嗅义,而非按指定順序傳入?yún)?shù)。

因?yàn)槲覀冊诒緯弦话嬷刑岬絉uby1.8將會(huì)支持這一特性隐砸,同時(shí)之碗,人們可以使用散列表來取得相同的效果,例如季希,可以考慮為我們的SongList加入更強(qiáng)大的按名搜索功能褪那。

class SongList
  def create_search(name, params)
    # ...
  end
end

list.create_search("short jazz songs", {
  'genre' => "jazz",
  'duration_less_than' => 270
})

第一個(gè)參數(shù)是搜索的名字,第二個(gè)是一個(gè)散列式式塌,其中包括搜索的參數(shù)博敬。使用散列表意味著我們可以模擬關(guān)鍵字:查詢類型為”爵士樂“, 且時(shí)長小于4分半的歌曲峰尝。不過這種方式有點(diǎn)笨重偏窝,并且一組大括號(hào)容易誤寫為一個(gè)和方法關(guān)聯(lián)的block。

因此武学,Ruby提供了一種快捷方式祭往,只要在參數(shù)列表中,散列數(shù)組在正常的參數(shù)之后火窒,并位于任何數(shù)組或block參數(shù)之前硼补,你就可以使用鍵值對,所有的這些對會(huì)被集合到一個(gè)散列數(shù)組中熏矿,并作為方法的一個(gè)參數(shù)傳入已骇。無須使用大括號(hào)。

list.create_search('short jazz songs',
  'genre'=>"jazz",
  'duration'=>270
)

最后票编,Ruby的慣用技法是褪储,你可以使用符號(hào)(Symbol)而非字符串作為參數(shù),符號(hào)清楚地表達(dá)了你所引用的是某個(gè)事物的名字栏妖。

list.create_search('short jazz songs',
  :genre => :jazz,
  :duration = 270
)

一個(gè)潛心編寫的Ruby程序通常包括許多方法乱豆,每個(gè)都很短小,因此熟悉定義和使用Ruby方法的各種選擇是非常值得的吊趾。

第七章 表達(dá)式(Expression)

Ruby和其他語言的一個(gè)不同之處就是任何東西都可能返回一個(gè)值:幾乎所有東西都是表達(dá)式宛裕。

明顯的一個(gè)好處就是實(shí)現(xiàn)鏈?zhǔn)秸Z句。

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

不太明顯的好處是论泛,C和Java中的普通語句在Ruby中也是表達(dá)式揩尸,例如,if和case語句都返回最后執(zhí)行的表達(dá)式的值屁奏。

song_type = if song.mp3_type == MP3::Jazz
  if song.written < Date.new(1935, 1, 1)
    Song::TradJazz
  else
    Song::Jazz
  end
  else  
    Song::other
  end

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

運(yùn)算符表達(dá)式(Operator Expression)

Ruby提供了基本的運(yùn)算符集(如+岩榆、-、*、/等等),也提供了幾個(gè)獨(dú)特的運(yùn)算符勇边。

實(shí)際上犹撒,Ruby中的許多運(yùn)算符是由方法調(diào)用來實(shí)現(xiàn)的,例如粒褒,當(dāng)你執(zhí)行 ab+c時(shí)识颊,實(shí)際上你是請求a對象執(zhí)行方法,傳入的參數(shù)是b奕坟。然后請求返回的結(jié)果對象執(zhí)行+方法祥款,傳入的參數(shù)是c。這等價(jià)于:

(a.*(b).+c)

因?yàn)槿魏螙|西都是對象月杉,而且你可以重新定義實(shí)例方法刃跛,所以你可以重新定義任何不滿足你需求的基本算術(shù)方法。

class Fixnum
  alias old_plus + # we can reference the original '+' as 'old_plus'
  # Redefine addition of Fixnums. This
  # is a BAD IDEA
  def +(other)
    old_plus(other).succ
  end
end

更有用的是苛萎,你寫的類可以像內(nèi)建那樣參與到運(yùn)算符表達(dá)式中桨昙,比如,你可能香蔥歌曲中間剪輯一段首懈,這可以用索引操作來實(shí)現(xiàn)绊率。

class Song
  def [](from_time, to_time)
    result = Song.new(self.title + " [extract]"),
    self.artist
    to_time - from_time
    result.set_start_time(from_time)
    result
  end
end

這段代碼擴(kuò)展了類Song:提供了[]方法,該方法有兩個(gè)參數(shù)(開始時(shí)間和結(jié)束時(shí)間)究履。它返回對應(yīng)給定時(shí)間間隔的一個(gè)新的song對象滤否。我們可以通過下面的代碼來試聽一首歌:

  song[0, 15].play

7.2 表達(dá)式之雜項(xiàng)
除了支持明顯的運(yùn)算符表達(dá)式和方法調(diào)用,以及不太明顯的語句表達(dá)(例如if和case)外最仑,Ruby的表達(dá)式還支持更多的東西藐俺。

7.2.1命令展開(Command Expansion)

如果你用反索引號(hào)(`), 或者以%x為前綴的分界形式泥彤,括起一個(gè)字符串欲芹,默認(rèn)情況下它會(huì)被當(dāng)做底層操作系統(tǒng)的命令來執(zhí)行。表達(dá)式的返回值就是該命令的標(biāo)準(zhǔn)輸出吟吝,由于沒有去處新行符菱父,所以你獲得的返回值結(jié)尾可能會(huì)有回車符或者換行符。

`date`
`ls`.split[34]
%x{echo "Hello there"}

你也可以在命令字符串中使用表達(dá)式展開和所有普通的轉(zhuǎn)義序列剑逃。

for i in 0..3
  status = 'dbmanager status id=#{1}'
  # ...
end

命令的退出狀態(tài)(exit status)保存在全局變量$?中浙宜。

重定義反引號(hào)

在前面的描述中,我們說反引號(hào)括起來的字符串”默認(rèn)“被當(dāng)做命令執(zhí)行蛹磺。實(shí)際上粟瞬,字符串被傳遞給了名為Kernel.方法(單引號(hào))。如果你愿意萤捆,可以重載它裙品。

alias old_backquote
  def `(cmd)
    result = old_backquote(cmd)
    if $? !=0
      fail "Command #{cmd} failed: #$?"
    end
    result
  end
print `data`
print `data`
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俗批,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子市怎,更是在濱河造成了極大的恐慌岁忘,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焰轻,死亡現(xiàn)場離奇詭異臭觉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)辱志,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狞膘,“玉大人揩懒,你說我怎么就攤上這事⊥旆猓” “怎么了已球?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辅愿。 經(jīng)常有香客問我智亮,道長,這世上最難降的妖魔是什么点待? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任阔蛉,我火速辦了婚禮,結(jié)果婚禮上癞埠,老公的妹妹穿的比我還像新娘状原。我一直安慰自己,他們只是感情好苗踪,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布颠区。 她就那樣靜靜地躺著,像睡著了一般通铲。 火紅的嫁衣襯著肌膚如雪毕莱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天颅夺,我揣著相機(jī)與錄音朋截,去河邊找鬼。 笑死碗啄,一個(gè)胖子當(dāng)著我的面吹牛质和,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播稚字,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼饲宿,長吁一口氣:“原來是場噩夢啊……” “哼厦酬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瘫想,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤仗阅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后国夜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體减噪,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年车吹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筹裕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窄驹,死狀恐怖朝卒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乐埠,我是刑警寧澤抗斤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站丈咐,受9級特大地震影響瑞眼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棵逊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一伤疙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧歹河,春花似錦掩浙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至键菱,卻和暖如春谬墙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背经备。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工拭抬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侵蒙。 一個(gè)月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓造虎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纷闺。 傳聞我的和親對象是個(gè)殘疾皇子算凿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 一份蝴、讀書筆記回顧昨天的收獲:什么是block、proc氓轰? block和proc是兩種不同的東西, block有形無...
    柳輝閱讀 383評論 0 0
  • 一婚夫、心得體會(huì)1、今天完成了什么署鸡? 看了Ruby核心案糙、Duck typing、類與對象靴庆、RUby安全 看10個(gè)con...
    柳輝閱讀 213評論 0 0
  • 一时捌、心得體會(huì)1、今天完成了什么炉抒? 看了6個(gè)小時(shí)的鎬頭書18章匣椰、21章、22章端礼,我想快速把書看一遍,然后看看哪些是需...
    柳輝閱讀 408評論 0 0
  • 一入录、讀書筆記3.4 剩余部分當(dāng)對象需要訪問同類的其他對象的內(nèi)部狀態(tài)時(shí)蛤奥,使用保護(hù)訪問(protected acces...
    柳輝閱讀 372評論 0 0
  • 酒店 都說巴厘島是一流的酒店,二流的沙灘僚稿。此行的酒店我們的領(lǐng)隊(duì)牛小晟是花了大功夫做的功課凡桥,我們一起住了四間酒店 檔...
    浮云小姐是造夢者閱讀 172評論 0 0