Scheme中list是怎麼實現的?
01-30
在Racket里創建了一個5百萬元素的list,存放的都是隨機數。
通過list-ref訪問第0個元素和最後一個元素的速度看上去差不多,感覺list中的元素可以像數組一樣隨機訪問,效率很高。本人初學,還沒達到分析源碼的水平。請高手答疑解惑:
- list採用了什麼優化方案,可以高效地隨機訪問list中的元素?
- list常用操作、以及在list首尾添加元素、鏈接兩個list等,效率怎麼樣?
- 提倡使用哪些list操作?應該盡量避免使用哪些list操作?
- 既然訪問list效率不差,vector存在的意義又是什麼?
要是list能隨機訪問,scheme標準里還要vector作甚?
其實隨機訪問和cons/car/cdr一個快了另一個就得慢下來,而且有Bootstrapping one-sided flexible arrays這種數據結構可以根據需求具體調節。。Okasaki的PFDS里就講了若干種random-access list的實現。。
但是。。Scheme是不會往標準裡面加這麼複雜的數據結構的。。開天闢地,唯cons/car/cdr足矣,pointer machine模型才是lisp,不,函數式語言的根基。。加入vector只是工程上的折衷。。你確定不是只是「看上去」么?
list 的原理就是用單鏈表實現的,確切地說實際上就是
list = null ;; () | { car : Any, cdr : Any }proper-list 不過就是其 cdr 必須也是 list 罷了
而對於單鏈表,list-ref 的複雜度就很明顯了:是 O(index),線性的
vector 就是數組實現 (array of Any),隨機訪問 (vector-ref) 就沒這個問題那麼對於其它的一些 list 操作,既然你明白了 list 的本質結構就是單鏈表,那麼相對應函數的複雜度就不難分析了對於一些簡單的 benchmark,TZ 我教你一招,最簡單的
循環若干次做同樣的事,然後時間差立馬就被放大了,效率差距就變得明顯了Lisp 里的 List 就是鏈表
struct cons {
lispObj* value; cons* cdr;};這種感覺推薦閱讀:
※Programming Languages: Application and Interpretation【譯13】
※某愉悅的scheme之旅(5)--從零開始實現模式匹配宏
※PLAI 編程環境簡單介紹
※PLAI前6章回顧
※Racket(Scheme)有哪些威力十足的庫?