斷斷續(xù)續(xù)花了很久才把這本書讀完,內(nèi)容比較雜,也不是特別深入,應(yīng)該是從日常的文章匯總而成,有些內(nèi)容還是值得一讀。而且可以看出作者并沒有仔細(xì)的整理這些內(nèi)容,關(guān)于對象和塊的章節(jié)重復(fù)和累贅部分很多,關(guān)于 Schewarzian Transform 也講了很多次。
1 我為什么開發(fā) Ruby
- 語言可以影響說話者的思想;
- 一個程序員不管他使用什么編程語言,他在一定時間里編寫的程序行數(shù)是一定的。
2 面向?qū)ο?/h1>
- 引入有限制的多重繼承應(yīng)該是一個好方法。
- 與繼承有關(guān)的內(nèi)容。
| 用語 | 內(nèi)容 |
|---|---|
| 單一繼承 | 只有一個父類,單純但存在幾個問題 |
| 多重繼承 | 多個父類,但引入了單一繼承沒有的新問題 |
| 靜態(tài)語言(Java) | 區(qū)分規(guī)格繼承和實現(xiàn)繼承 |
| 動態(tài)語言 | 只有實現(xiàn)繼承 |
| 規(guī)格多重繼承的問題 | Java 的接口可以解決 |
| 實現(xiàn)多重繼承的問題 | Mix-in 可以解決 |
| Mix-in | 所有支持多重繼承的語言都可以考慮使用 |
| Ruby 的 Mix-in | 強(qiáng)制使用模塊,來解決多重繼承的問題 |
- 靜態(tài)語言中可以實現(xiàn)多態(tài)性的只是限于擁有共通父類的對象。
- 數(shù)據(jù)要記錄與自己數(shù)據(jù)類型有關(guān)的信息。這樣的數(shù)據(jù)類型稱為動態(tài)類型。
- 靜態(tài)類型,直接執(zhí)行,速度快。
- 動態(tài)類型,邊解釋源代碼邊執(zhí)行速度慢。優(yōu)點(diǎn),靈活性。
3 程序塊
- C 語言是通過函數(shù)指針來把函數(shù)作為一種對象來處理的。
- 在塊中可以引用外部局部變量的方法,說明塊不知是簡單的程序代碼,而且把外部“環(huán)境”也包括了進(jìn)來,想這樣的塊稱為閉包。
- 在被調(diào)用的方法中有兩種方式來使用傳遞來的塊。一種是用“塊參數(shù)”的方式明確聲明接受塊作為參數(shù),另一種是使用yield這個Ruby的保留詞。
def each(&block)
i = 0
while i < self.size
block.call(self[i])
i+=1
end
end
def each()
i=0
while i < self.size
yield self[i]
i+=1
end
end
塊作為參數(shù)的優(yōu)點(diǎn):
- 明確表示了塊處理;
- 塊和對象一樣被統(tǒng)一處理了;
- 檢查參數(shù)是否為 nil 就可以判斷是否傳遞了塊參數(shù)。
yield 的優(yōu)點(diǎn):
- 沒有用到閉包,執(zhí)行速度稍快;
- 錯誤信息比較用一理解。
- sort_by 用執(zhí)行的代碼塊生成的結(jié)果拍續(xù),對每個元素只執(zhí)行一次塊的調(diào)用。與其說是比較兩個元素,更多的時候是對每個元素進(jìn)行某種處理,用處理的結(jié)果來排序。(原來如此)。
- 用塊來保證程序的后處理。
3.2.5 Enumerable 的局限(贊)
Enumerable 的兩個主要缺點(diǎn):
- 循環(huán)都依賴 each 方法,而且不能并行執(zhí)行;
- 從多個對象取出元素進(jìn)行處理比較難寫。
用 Ruby 來定義 zip 方法的話,到目前為止,因為沒有提供外部迭代器,所以只能在內(nèi)部把參數(shù)變換成數(shù)組來對應(yīng)。把參數(shù)作成數(shù)組,有以下兩個問題:
- 大量的數(shù)據(jù)變換成數(shù)組會造成資源的浪費(fèi);
- 不能處理無限循環(huán)的 Enumerable。
代碼部分:
module Enumerable
def zip(*args)
n = 0
args = args.map{|a| a.to_a }
self.each do |x|
yield [x, *args.map{|a| a[n] }]
n += 1
end
end
end
可以修改為:
module Enumerable
def zip(*args)
args = args.map{|a| a.enum_for(:each) }
self.each do |x|
yield [x, *args.map{|a|
a.next rescue nil
}]
end
end
end
- 不要變換成數(shù)組,而是用 enum_for 方法變換成以 each 為基礎(chǔ)的 Enumerator。如果是 Ruby 1.8.7 ,這部分可以通過調(diào)用塊的 each 方法來實現(xiàn),但是如果這個類沒有 each 方法,可能不返回 Enumerator。所以用 enum_for 方法才是安全的。
- 如果參數(shù)用數(shù)組可能會消耗很大內(nèi)存。
4 設(shè)計模式
- 設(shè)計模式的本質(zhì),并不是介紹至今沒有用過的新模式,而是通過給屢屢使用過的模式起一個合適的名字,從而提供了設(shè)計時的詞匯。
- 舊約全書里記載了巴比倫塔的故事,描寫了人與人之間因為語言不通,而中止了塔的建設(shè),人們紛紛散去的場面。語言的重要性可見一斑。(溝通的重要性)。
5 Ajax (建議粗讀,內(nèi)容有點(diǎn)老,而且也比較淺)
6 Ruby on Rails
6.2.3 猴子補(bǔ)丁技巧
** undef **
undef 有把方法定義取消的功能。用 undef 不僅可以取消本類中的方法,也可以取消父類中的方法。
** remove_method **
remove_method 僅取消本類中的方法。
alias
用 undef 或 remove_method 刪除了以前方法后,別名的方法依然可以使用。別以 alias 只是起別名,而是重新定義了一個方法。
7 文字編碼(不感興趣可以跳過)
文字編碼的難度還是很大的。
正則表達(dá)式(贊)(要比Ruby鎬頭書和元編程介紹的詳細(xì))
| 錨點(diǎn) | 匹配位置 |
|---|---|
| ^ | 行首 |
| $ | 行尾(若含換行,則是其前面的字符) |
| \A | 字符串頭 |
| \Z | 字符串尾(若含換行,匹配前一字符) |
| \z | 字符串尾 |
| \b | 詞頭或詞尾([] 外) |
| (?=) | 用模式指定位置 |
| (?!) | 用否定模式制定位置 |
*貪婪與懶惰 **
這是一個經(jīng)常討論的問題,記得加 .
分組
使用向后引用的時候,因為要在內(nèi)部保存數(shù)據(jù),效率會受影響。如果僅僅為了分組,而不需要使用向后引用,可以使用沒有向后飲用的模式括號(?:)。
錨點(diǎn)
| 錨點(diǎn) | 匹配位置 |
|---|---|
| ^ | 行首 |
| $ | 行尾(若含換行,則是其前面的字符) |
| \A | 字符串頭 |
| \Z | 字符串尾(若含換行,匹配前一字符) |
| \z | 字符串尾 |
| \b | 詞頭或詞尾([] 外) |
| (?=) | 用模式指定位置 |
| (?!) | 用否定模式制定位置 |
| 選項 | 含義 |
|---|---|
| i | 不區(qū)分大小寫 |
| m | 復(fù)數(shù)行匹配 |
| o | 只展開一次 |
| x | 無視正則表達(dá)式的空格,注釋有效 |
選項
| 選項 | 含義 |
|---|---|
| i | 不區(qū)分大小寫 |
| m | 復(fù)數(shù)行匹配 |
| o | 只展開一次 |
| x | 無視正則表達(dá)式的空格,注釋有效 |
注釋
/\d{4}-? #year
\d{1,2}-? #month
\d{1,2} #day
/x
8.1.7 特殊變量
$& 最后匹配字符串
8.1.9 split 的本質(zhì)
- 用固定字符串分割字符串
- 用正則來分隔
- 如果不想去掉標(biāo)簽,而是將其保存下來,可以用括號將模式包起來。
str = "<ul><li>a</li>b</ul>"
str.split(/(<.*?>)/)
# ["", "<ul>", "", "<li>", "a", "</li>", "b", "</ul>"]
8.1.10 字符串掃描
"afdasfasdfads".scan(/fa./){|s| p s }
下面代碼執(zhí)行同樣的動作。它不生成無用的數(shù)組,效率稍高一點(diǎn)。(誰能告訴我為什么?)
"afdasfasdfads".scan(/fa./).each{|s| p s }
8.1.11 置換
置換字符串
a = 'abbbcd'
a.gsub(/a(b+)/, "#{$1}") #wrong
a.gsub(/a(b+)/, "\1") #wrong
a.gsub(/a(b+)/, "\\1") #right
a.gsub(/a(b+)/, '\1') #right
a.gsub(/a(b+)/, '\\1') #right
a.gsub(/a(b+)/){ $1 } #right
居然'\1'和'\1'都可以!