每個Racket模塊都存在自己的文件。
#lang racket
(provide print-cake)
;draws a cake with n candles
(define (print-cake n)
(show " ~a " n #\.)
(show " .-~a-. " n #\|)
(show " | ~a | " n #\space)
(show "---~a---" n #\-))
(define (show fmt n ch)
(printf fmt (make-string n ch))
(newline))
其它模塊可以引入cake.rkt來使用print-cake函數(shù),因?yàn)閜rovid行明確導(dǎo)出了print-cake函數(shù)。而show函數(shù)時私有,因?yàn)樗鼪]有導(dǎo)出。
#lang racket
(require "cake.rkt")
(print-cake (random 30))
"cake.rkt"通過require導(dǎo)入相同目錄的文件。unix風(fēng)格的相對目錄在所以平臺上用來作為相對模塊引用。
6.1.1組織模塊
上面代碼的列子展示了最通用模塊代碼組織方式:把所有的文件放在一個目錄或者子目錄里,然后通過相對路徑來引用。模塊的目錄能被當(dāng)成一個項(xiàng)目,因?yàn)樗苷麄€在系統(tǒng)文件里移動或者拷貝到其它機(jī)器上,相對路徑保存了彼此之間的模塊連接。
racket工具都會自動使用相對路徑來工作。比如
racket sort.rkt
在命令行運(yùn)行上述命令會自動加載編譯相關(guān)模塊。如果程序足夠大,從源代碼編譯太耗時間,可以使用
raco make sort.rkt
命令來編譯"sort.rkt"和它依賴的文件到字節(jié)碼文件。再運(yùn)行
racket sort.rkt將會自動使用字節(jié)碼文件當(dāng)它們存在的時候。
6.1.2庫集合
一個集合是一個層次組織的一按的庫模塊。集合易用通過一個沒有引號和后最的路徑。
當(dāng)你搜索在線文檔,搜索結(jié)果就表明了提供綁定的模塊。當(dāng)你在文檔里點(diǎn)擊一個超鏈接,停留在綁定名稱上也可以顯示提供它的模塊。
一個模塊的引用像racket/date看上去像一個標(biāo)識符,但是它其實(shí)不會被當(dāng)做標(biāo)識符處理,它會轉(zhuǎn)化成基于集合的引用
- 首先,如果路徑?jīng)]有/,
require會自動添加/main。比如require slideshow等價于require slideshow/main - 其次,
require隱式添加".rkt"后綴 - 最后,
require通過安裝的集合搜索路徑,而不是把路徑當(dāng)成相對于封閉的模塊路徑
一個集合實(shí)現(xiàn)像一個文件系統(tǒng)目錄。但是這只是require查找的其中一個地方。包括用戶定義目錄,還有PLTCOLLECTS配置的路徑,還有安裝的包都是查找的范圍。
6.1.3包和集合
包是安裝在racket包管理器的庫集合(包括已經(jīng)預(yù)先安裝在racket分發(fā)包里的)。比如racket/gui由gui提供,paser-tools/lex由parser-tools提供。
racket程序不直接引用包。程序通過集合引用庫,添加或者移除包會改變集合庫。集合可以安裝不同的包,但是包管理器會保證不發(fā)生沖突。相見包管理的文檔。
6.1.4添加集合
回顧上面的例子,假設(shè)db和mechine模塊都需要幫助函數(shù)。幫助函數(shù)能放在util目錄下,而db和mechine都能通過相對路徑../utils/來引用。一個程序員可以按照相關(guān)路徑來引用而不用知道你的racket配置。
一些庫是給多個項(xiàng)目使用的,所以把這個庫的源代碼放在和使用它的模塊一起并沒有什么意義。在這種情況下,最好添加一個新的集合。當(dāng)這個庫被安裝到集合以后,她就能用沒有引號的方式引用,就像racket分發(fā)包里的庫一樣。
你能添加一個新的集合,只要在racket的安裝目錄放置文件,也可以在函數(shù)get-collects-search-dirs返回的目錄。此外,你也可以設(shè)置PTLCOLLECTS變量來添加搜索目錄。當(dāng)然,直接添加一個包的方式是最佳選擇。
創(chuàng)建一個包并不意味著你必須注冊這個包或者執(zhí)行打包步驟復(fù)制源代碼到一個歸檔文件。創(chuàng)建一個包只是簡單的意味著包管理器使你的包可以在本地像集合一樣被訪問。
舉例來說,假設(shè)你有一個目錄/usr/molly/bakery包含cake.rkt模塊以及相關(guān)模塊。為了讓這個模塊可以像bakery集合一樣,你可以
- 使用明令行中的raco命令
rako pkg install --link /usr/molly/bakery
--link參數(shù)不是必須的,當(dāng)目錄里有分隔符的時候,你可以省略。 - 使用DrRacket包管理選項(xiàng)(在文件目錄下)。執(zhí)行該選項(xiàng),選擇目錄/usr/molly/bakery,然后安裝。
在這之后,只要使用(require bakery/cake)就能引用這個模塊下的函數(shù)。
默認(rèn)情況下,你安裝的目錄名字被當(dāng)做包名和集合名來使用。淡然,包管理器安裝的庫也只對當(dāng)前用戶有效,如果想對所有人有效,可以看racket包管理章節(jié)。
如果你打算分發(fā)你的包,請小心選擇你的包名。集合的命名空間是分層的,但是頂級的集合名是全局的,而且包的命名空間是平的??梢允褂孟?code>molly一樣的標(biāo)識符來區(qū)分作者,然后把庫放在洗面。
當(dāng)你的包被安裝到集合以后,你還是可以使用raco命令編譯庫源碼,使用raco setup更好。它使用集合名病情編譯集合里的所有庫。此外,它還會構(gòu)建集合文檔到文檔索引,當(dāng)你在集合里指定了info.rkt。