国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Ruby之symbol研究
這是一個(gè)研究筆記,主要是為了向同好請(qǐng)教。除了這個(gè)開頭以外,沒有多余的廢話,也就免了其他的客套。請(qǐng)大家不要抱怨可讀性不好。

1. 在一個(gè)名字或者字符串前面加上冒號(hào),得到一個(gè)symbol對(duì)象。還可以通過(guò)String#to_sym、Fixnum#to_sym和String#intern得到。

2. 一般用symbol做hash的key,號(hào)稱是為了節(jié)省內(nèi)存,提高執(zhí)行效率。

3. 為什么可以節(jié)省內(nèi)存?Ruby中的String是可變對(duì)象,這一點(diǎn)跟Java、C#、Python都不一樣。注意跟某些C++標(biāo)準(zhǔn)庫(kù)中的COW的basic_string<T>也不一樣。Ruby中每一個(gè)String都可以就地改變。可能是因?yàn)檫@個(gè)原因,Ruby中兩個(gè)內(nèi)容相同的字符串文本量實(shí)際上是兩個(gè)不同的對(duì)象。

    a = "hello"
    b = "hello"

    雖然倆字符串內(nèi)容都一樣,但是你比一下a和b,就知道a.object_id != b.object_id,它們指向的不是同一個(gè)對(duì)象。結(jié)果反而很像未經(jīng)string pooling優(yōu)化的C語(yǔ)言的行為。到底immutable好還是mutable好,或者還是貌似聰明的COW好,見仁見智了。不過(guò)Ruby的設(shè)計(jì)在把字符串用作hash key的時(shí)候毛病就大了。比如你寫:

    h["ruby"].name   = "Ruby"
    h["ruby"].author = "matz"
    h["ruby"].birth_year = 1995

的時(shí)候,"ruby"這個(gè)字符串動(dòng)態(tài)生成了三次,占用三倍內(nèi)存。這就嚴(yán)重地浪費(fèi)了內(nèi)存。而用:ruby做為key,因?yàn)樵谡麄€(gè)運(yùn)行過(guò)程中,Ruby runtime保證名為:ruby的symbol對(duì)象只有一個(gè),所以就不用生成三個(gè),節(jié)省內(nèi)存。

4. 為什么可以提高執(zhí)行效率?顯然的原因是免得多次動(dòng)態(tài)生成‘ruby‘字符串了。還不單如此,Hash的key值應(yīng)該是常量,所以Ruby的Hash對(duì)于作為key的String對(duì)象都要施加保護(hù),所謂保護(hù),也就是把String凍結(jié)了,免得你之后還改變其值。保護(hù)當(dāng)然是有代價(jià)的,symbol無(wú)需保護(hù),當(dāng)然是能提高效率的。附帶說(shuō)明,其他mutable的對(duì)象也可以作為hash的key,這是Ruby設(shè)計(jì)得比較奇怪的地方。在irb里運(yùn)行以下代碼,你會(huì)發(fā)現(xiàn)Ruby的Hash丟值。

    h = Hash.new
    L = [1, 2]
    h[L] = "A big object!"
    L << 3 # 居然能改!
    h[L]   # ==> nil,找不到了,似乎正常
    # 可是
    h[[1, 2]]  # ==> nil,居然還是找不到
    # 看看keys
    h.keys     # ==> {[1, 2, 3]} 似乎還在里面
    h[[1, 2, 3]] # ==> nil
    # 可是
    h          # ==> {[1, 2, 3]=>‘A big object‘},明明在這里,就是找不到

    h.rehash  # ==> 這樣就會(huì)一切恢復(fù)正常。
   
    這一點(diǎn)上Python的設(shè)計(jì)要比較容易理解,list根本就是unhashable的,不能用來(lái)做hash的key。

        回過(guò)頭來(lái)在說(shuō)提高效率的事。Symbol效率提高還有第三個(gè)原因,那是因?yàn)閟ymbol本質(zhì)上不比一個(gè)整數(shù)多出多少東西,用Symbol#to_i可以得到一個(gè)在整個(gè)程序中唯一的整數(shù)。Hash完全可以利用這個(gè)整數(shù)來(lái)產(chǎn)生hash值,那豈不是比根據(jù)字符串內(nèi)容去算hash值快得多?這還是小意思,既然這個(gè)整數(shù)是唯一的,那么產(chǎn)生一個(gè)唯一的hash值也就是小菜一碟,要是能保證hash值唯一,那還是什么hash表,根本就變成數(shù)組了。Hash表還可能會(huì)沖突,數(shù)組根本不會(huì)沖突,百分之百保證O(1),當(dāng)然快。我沒看Ruby源碼,不知道是不是這么處理的。

5. 為什么Ruby runtime可以保證每一個(gè)symbol唯一?因?yàn)镽uby把symbol存放在運(yùn)行時(shí)維護(hù)的一個(gè)符號(hào)表里了,而這個(gè)符號(hào)表實(shí)際上是一個(gè)atom數(shù)據(jù)結(jié)構(gòu),其中存儲(chǔ)著當(dāng)前所有的程序級(jí)的name,確保不出現(xiàn)內(nèi)容相同的多個(gè)對(duì)象。幾乎每一個(gè)語(yǔ)言和系統(tǒng)都會(huì)有這樣一個(gè)符號(hào)表,只不過(guò)象C/C++那樣的語(yǔ)言,這個(gè)符號(hào)表只是在編譯時(shí)存在,運(yùn)行時(shí)就沒了。而Python、Ruby則在運(yùn)行時(shí)也保留這張表備用。有這樣一個(gè)現(xiàn)成的數(shù)據(jù)結(jié)構(gòu)干嘛不用?

6. 但是這個(gè)表中存放的并不光是我們自己主動(dòng)生成的symbols,還有Ruby解釋器對(duì)當(dāng)前程序進(jìn)行詞法分析、語(yǔ)法分析后存在其中的、當(dāng)前程序的所有名字。這可是Ruby引擎用的東西啊,我們只要加上一個(gè)冒號(hào),就讓自己的對(duì)象跟Ruby引擎內(nèi)部使用的對(duì)象成鄰居了。所以String#intern這個(gè)方法叫做intern(內(nèi)部化)。

   .NET Framework中String類也有一個(gè)Intern方法,意思是一樣一樣一樣的,在李建忠的經(jīng)典譯本里翻譯為“駐留”。

7. 可以用Symbol#all_symbols查看當(dāng)前定義的全部symbol??梢泽w驗(yàn)一下自己往符號(hào)表中塞一個(gè)對(duì)象的感覺,想想你寫的程序跟Ruby引擎能干一樣的事情,應(yīng)該還是挺爽的。

8. Python中用不著這個(gè),因?yàn)樽址莍mmutable的。放下有用沒用不說(shuō),有沒有辦法在Python中intern呢?我還沒找到辦法。有沒有Python牛知道?

     補(bǔ)充一下:查到了,Python中做這個(gè)事情的函數(shù)叫做 intern()。

9. 我覺得Ruby的這個(gè)設(shè)計(jì)是從Perl的glob中簡(jiǎn)化而來(lái)的。Perl中可以用*a得到對(duì)應(yīng)于符號(hào)a的glob,那是一個(gè)八爪魚一樣的怪物。Ruby也可以很容易的得到symbol table中的對(duì)象,不過(guò)沒有把symbol設(shè)計(jì)成八爪魚。

10. 還有一些小問(wèn)題沒搞清楚,比如:name跟@name是什么關(guān)系。attr_reader :name,實(shí)際上是給attr_reader方法傳了一個(gè)symbol作為參數(shù),前者要通過(guò)這個(gè)symbol找到@name變量,是不是‘@‘ + :name.id2name這么簡(jiǎn)單?大概可以去看看source了。

   



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1255966

[點(diǎn)擊此處收藏本文]   孟巖發(fā)表于 2006年09月20日 22:56:00


IDG投資,直接引進(jìn)北美IT技術(shù)成立的培訓(xùn)中心
已經(jīng)培養(yǎng)了5000多名學(xué)員,平均工資4000以上.

http://www.tarena.co...

熱點(diǎn)圖書連載、試讀
名人堂/書友會(huì)/特色書架

http://book.csdn.net

高薪?jīng)]有捷徑——唯有專業(yè)享受高薪 簽北京就業(yè)合同

http://www.uplooking...

Csdn提供的廣告   Csdn  Tag

 
蛋蛋 發(fā)表于2006-09-21 00:39:00  IP: 199.246.40.*
孟老大猜錯(cuò)了哈。符號(hào)這個(gè)概念是Matz從Lisp里引進(jìn)的??纯碈ommon Lisp的代碼,符號(hào)無(wú)處不在哈。:name和@name和name()的關(guān)系是由生成accessor的函數(shù)定的,當(dāng)然不是‘◎’+:name.id2name那么簡(jiǎn)單。用attr_reader這個(gè)函數(shù)為例:你把:name這個(gè)符號(hào)傳給attr_reader這個(gè)函數(shù)。attr_reader根據(jù):name生成name()這個(gè)函數(shù)(當(dāng)然真正的實(shí)現(xiàn)有很多具體考慮):
def name()
@name
end

不信你可以寫自己的attr_reader:
class T
def T.my_attr_reader(name)
class_eval <<-READER
def #{name}
@#{name};
end
READER
end
my_attr_reader :name
def set_name(name)
@name=name;
end
end

t = T.new
t.set_name(‘myan‘);
puts t.name

打印結(jié)果就是‘myan‘了。

再說(shuō)了,attr_reader()不一定只接受符號(hào)哈:
attr_reader :name
attr_reader "name"
attr_reader :name.to_s
attr_reader "name".to_sym
都一樣的。

思考題:寫一個(gè)自己的attr_accessor()。

Symbol的意義不僅在于充當(dāng)一個(gè)名字提高點(diǎn)性能,或者充當(dāng)某個(gè)對(duì)象的標(biāo)識(shí)符。Symbol對(duì)象代表代碼解析樹里的每個(gè)token。比如說(shuō)def foo; "foo"; end。除了"foo",每個(gè)token, def, foo, end什么的都有對(duì)應(yīng)的符號(hào)。換句話說(shuō),符號(hào)為我們提供了進(jìn)入Ruby解析樹的大門。不定哪天我們就可以利用符號(hào)直接操作部分解析的Ruby代碼了。換句話說(shuō),我們可以超越各式eval, 進(jìn)入人見人耐的macro世界了。慢慢等吧。哈哈哈!

 
蛋蛋 發(fā)表于2006-09-21 00:49:00  IP: 199.246.40.*
P.S., 孟老大的學(xué)習(xí)還是比較仔細(xì)和全面的嘛。CSDN不少大嘴巴"專家"明明缺乏對(duì)編程語(yǔ)言的基本了解(比如開篇就來(lái)什么被解釋的語(yǔ)言就是動(dòng)態(tài)語(yǔ)言一類),卻酷耐指點(diǎn)江山,臧否語(yǔ)言,實(shí)在應(yīng)該好好學(xué)學(xué)孟老大的踏實(shí)哈。CSDN辦個(gè)專題怎么樣?普及一下編程語(yǔ)言的基本知識(shí),比如語(yǔ)義的重要性(設(shè)計(jì)語(yǔ)言總得知道自己要解決什么問(wèn)題吧?),常見的范式(太多老大言必OO,動(dòng)不動(dòng)就叫囂我的xxx是最好的),類型(工業(yè)界和學(xué)術(shù)界的研究熱點(diǎn)哈),常見語(yǔ)言特性(免得universee給closure取了個(gè)別名就開始吹噓自己的2B語(yǔ)言了),常見設(shè)計(jì)思路什么的。像云風(fēng)那樣認(rèn)真讀過(guò)Programming Language Pragmatics這類教材的高手還是應(yīng)該不少的。程序語(yǔ)言要從娃娃抓起啊。

 
myan 發(fā)表于2006-09-21 07:39:00  IP: 221.218.165.*
to 蛋蛋:
謝謝你的指教。這樣看來(lái),attr_reader之類的函數(shù)反而是主要接受字符串了。只不過(guò)"#{sym}"可以自動(dòng)對(duì)sym調(diào)用to_s轉(zhuǎn)型。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Ruby一些筆記
理解 Ruby Symbol (Ruby中的冒號(hào))
牛人點(diǎn)評(píng)Ruby語(yǔ)言十大令人喜愛的特點(diǎn)(1) - 51CTO.COM
ruby筆記
FreeMarker開發(fā)指南
ruby系列教材(26):More about methods(3)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服