3.模塊化編碼 (newLISP 代碼模式 v.10.6.2)

程序的構(gòu)建

當(dāng)你編寫的程序越來越大或者多人在同一代碼庫(kù)協(xié)作開發(fā)時(shí)闹获,將代碼劃分成不同的模塊是很有必要的. newLISP中使用context來創(chuàng)建模塊, 也就是命名空間. 命名空間將各個(gè)模塊之間的詞法隔離開. 這樣各模塊可以擁有相同名字的變量而不會(huì)發(fā)生沖突.

通常钓试,每個(gè)文件都有一個(gè)context來組織模塊.可能一個(gè)模塊文件包含數(shù)據(jù)庫(kù)訪問代碼.

? ? ; database.lsp

? ? ;

? ? (context 'db)

? ? (define (update x y z)

? ? ...

? ? )

? ? (define (erase x y z)

? ? ...

? ? )

另一個(gè)模塊包含多種數(shù)據(jù)操作代碼.

? ? ; auxiliary.lsp

? ? ;

? ? (context 'aux)

? ? (define (getval a b)

? ? ...

? ? )

最后猿涨,會(huì)有一個(gè)主模塊 MAIN 加載和控制所有其他模塊:

? ? ; application.lsp

? ? ;

? ? (load "auxiliary.lsp")

? ? (load "database.lsp")

? ? (define (run)

? ? ? ? (db:update ....)

? ? ? ? (aux:putval ...)

? ? ? ? ...

? ? ? ? ...

? ? )

? ? (run)

一個(gè)文件多個(gè)模塊

當(dāng)在一個(gè)文件中使用多個(gè)context時(shí)悼泌,每一個(gè)context都要以(context MAIN)來關(guān)閉:

? ? ; myapp.lsp

? ? ;

? ? (context 'A)

? ? (define (foo ...) ...)

? ? (context MAIN)

? ? (context 'B)

? ? (define (bar ...) ...)

? ? (context MAIN)

? ? (define (main-func)

? ? ? ? (A:foo ...)

? ? ? ? (B:bar ...)

? ? )

注意在創(chuàng)建context A 和 B 的時(shí)候,他們的名字前都有單引號(hào),這是因?yàn)樗麄兪切聞?chuàng)建的. 但是 MAIN 前沒有使用單引號(hào),這是因?yàn)?newLISP 在啟動(dòng)時(shí)就已經(jīng)創(chuàng)建了MAIN. 當(dāng)然, 給他加個(gè)引號(hào)也沒有問題.

可以使用下面的技術(shù)合并掉 (context MAIN)語句:

? ? ; myapp.lsp

? ? ;

? ? (context 'A)

? ? (define (foo ...) ...)

? ? (context 'MAIN:B)

? ? (define (bar ...) ...)

? ? (context 'MAIN)

? ? (define (main-func)

? ? ? ? (A:foo ...)

? ? ? ? (B:bar ...)

? ? )

(context 'MAIN:B) 回到 MAIN 并創(chuàng)建一個(gè)新的context B.

默認(rèn)函數(shù)

每一個(gè)模塊都可以有一個(gè)和宿主context同名的函數(shù). 這個(gè)函數(shù)有著特殊的作用:

? ? (context 'foo)

? ? (define (foo:foo a b c)

? ? ...

? ? )

函數(shù) foo:foo 就是模塊 foo的默認(rèn)函數(shù), 因?yàn)楫?dāng)使用模塊名foo 的時(shí)候就像調(diào)用一個(gè)函數(shù), 他將會(huì)被自動(dòng)的映射到 foo:foo

? ? (foo x y z)

? ? ; same as

? ? (foo:foo x y z)

默認(rèn)函數(shù)看起來像普通函數(shù),但是它擁有自己的名命名空間也榄。我們可以用此特性來編寫保持?jǐn)?shù)據(jù)狀態(tài)的函數(shù):

? ? (context 'generator)

? ? (define (generator:generator)

? ? ? ? (inc acc)) ; when acc is nil, assumes 0

? ? (context MAIN)

? ? (generator) → 1

? ? (generator) → 2

? ? (generator) → 3

下面是個(gè)更復(fù)雜的例子,用來生成斐波納契序列:

? ? (define (fibo:fibo)

? ? ? ? (if (not fibo:mem) (set 'fibo:mem '(0 1)))

? ? ? ? (last (push (+ (fibo:mem -1) (fibo:mem -2)) fibo:mem -1)))

? ? (fibo) → 1

? ? (fibo) → 2

? ? (fibo) → 3

? ? (fibo) → 5

? ? (fibo) → 8

? ? ...

這個(gè)示例還展示了如何在不顯示創(chuàng)建context的情況下動(dòng)態(tài)定義默認(rèn)函數(shù)。作為另一種選擇兵迅,也可以在明確創(chuàng)建context下定義默認(rèn)函數(shù):

? ? (context 'fibo)

? ? (define (fibo:fibo)

? ? ? ? ? ? (if (not mem) (set 'mem '(0 1)))

? ? ? ? ? ? (last (push (+ (mem -1) (mem -2)) mem -1)))

? ? (context MAIN)

? ? (fibo) → 1

? ? (fibo) → 2

? ? (fibo) → 3

? ? (fibo) → 5

? ? (fibo) → 8

雖然第一種形式較短,但是第二種形式更容易閱讀.

用context封裝數(shù)據(jù)

前面的例子展示了用命令空間中的默認(rèn)函數(shù)來封裝數(shù)據(jù). 在 generator 的例子中 acc 用來保存狀態(tài). 在 fibo 的例子中用 mem 來保存增長(zhǎng)的列表. 兩個(gè)例子里,函數(shù)和數(shù)據(jù)在一個(gè)命名空間中共存. 下面的例子展示了如何僅在命名空間的默認(rèn)函數(shù)中保存數(shù)據(jù):

? ? (set 'db:db '(a "b" (c d) 1 2 3 x y z))

就像使用默認(rèn)函數(shù) fibo 和 generator 那樣,我們可以用 db來調(diào)用 db:db . 此時(shí)db就像普通list一樣,可以完成任意的列表操作:

? ? (db 0)? ? → a

? ? (db 1)? ? → "b"

? ? (db 2 1)? → d

? ? (db -1)? → z

? ? (db -3)? → x

? ? (3 db)? ? → (1 2 3 x y z)

? ? (2 1 db)? → ((c d))

? ? (-6 2 db) → (1 2)

用引用傳遞對(duì)象

當(dāng)默認(rèn)函數(shù)被作為某個(gè)函數(shù)的參數(shù)調(diào)用的時(shí)候, 默認(rèn)函數(shù)會(huì)通過引用傳遞. 這意味這傳遞給函數(shù)的參數(shù)是原始數(shù)據(jù), 而不是列表或者字符串的拷貝. 在傳遞龐大的數(shù)據(jù)的時(shí)候這個(gè)特性非常有用:

? ? (define (update data idx expr)

? ? ? ? (if (not (or (lambda? expr) (primitive? expr)))

? ? ? ? ? ? (setf (data idx) expr)

? ? ? ? ? ? (setf (data idx) (expr $it))))

? ? (update db 0 99) → a

? ? db:db → (99 "b" (c d) 1 2 3 x y z)

? ? (update db 1 upper-case) → "b"

? ? db:db → (99 "B" (c d) 1 2 3 x y z)

? ? (update db 4 (fn (x) (mul 1.1 x))) →

? ? db:db → (99 "B" (c d) 1 2.2 3 x y z)

db:db 中的數(shù)據(jù)通過變量 data 傳遞給函數(shù) update , 現(xiàn)在update就擁有一個(gè) context db的數(shù)據(jù)引用. 接著判斷傳入的 expr 參數(shù)是否是系統(tǒng)函數(shù),操作符或者用戶定義的函數(shù)的,如果是的話就使用expr 操作 it , it是一個(gè)系統(tǒng)變量包含了表達(dá)式(這里是setf)要操作的原始數(shù)據(jù)(data idx).

當(dāng)一個(gè)newLISP函數(shù)需要一個(gè)列表或者在字符串參數(shù)的時(shí)候, 使用context的名稱就能將默認(rèn)函數(shù)傳遞進(jìn)去. 示例如下:

? ? (define (pop-last data)

? ? (pop data -1))

? ? (pop-last db) → z

? ? db:db? ? ? ? → (99 "B" (c d) 1 2.2 3 x y)

update 同時(shí)也展示了如何將函數(shù)作為數(shù)據(jù)傳遞給別的函數(shù) (upper-case 也依靠 $it). 更多內(nèi)容請(qǐng)看函數(shù)即數(shù)據(jù).

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末薪贫,一起剝皮案震驚了整個(gè)濱河市恍箭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌后雷,老刑警劉巖季惯,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異臀突,居然都是意外死亡勉抓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門候学,熙熙樓的掌柜王于貴愁眉苦臉地迎上來藕筋,“玉大人,你說我怎么就攤上這事梳码∫” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵掰茶,是天一觀的道長(zhǎng)暇藏。 經(jīng)常有香客問我,道長(zhǎng)濒蒋,這世上最難降的妖魔是什么盐碱? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮沪伙,結(jié)果婚禮上瓮顽,老公的妹妹穿的比我還像新娘。我一直安慰自己围橡,他們只是感情好暖混,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翁授,像睡著了一般拣播。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上收擦,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天诫尽,我揣著相機(jī)與錄音,去河邊找鬼炬守。 笑死,一個(gè)胖子當(dāng)著我的面吹牛剂跟,可吹牛的內(nèi)容都是我干的减途。 我是一名探鬼主播酣藻,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鳍置!你這毒婦竟也來了辽剧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤税产,失蹤者是張志新(化名)和其女友劉穎怕轿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辟拷,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撞羽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衫冻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诀紊。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖隅俘,靈堂內(nèi)的尸體忽然破棺而出邻奠,到底是詐尸還是另有隱情,我是刑警寧澤为居,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布碌宴,位于F島的核電站,受9級(jí)特大地震影響蒙畴,放射性物質(zhì)發(fā)生泄漏贰镣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一忍抽、第九天 我趴在偏房一處隱蔽的房頂上張望八孝。 院中可真熱鬧,春花似錦鸠项、人聲如沸干跛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楼入。三九已至,卻和暖如春牧抽,著一層夾襖步出監(jiān)牢的瞬間嘉熊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工扬舒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阐肤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像孕惜,于是被迫代替她去往敵國(guó)和親愧薛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

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