轉自:http://www.cppblog.com/cslover/archive/2013/12/21/204934.html
Lua提供高級的require函數來加載運行庫。粗略的說require和dofile完成同樣的功能但有兩點不同:
1. require會搜索目錄加載文件
2. require會判斷是否文件已經加載避免重復加載同一文件。由於上述特征,require在Lua中是加載庫的更好的函數。
require使用的路徑和普通我們看到的路徑還有些區別,我們一般見到的路徑都是一個目錄列表。require的路徑是一個模式列表,每一個模式指明一種由虛文件名
(require的參數)轉成實文件名的方法。更明確地說,每一個模式是一個包含可選的問號的文件名。匹配的時候Lua會首先將問號用虛文件名替換,然后看是否有
這樣的文件存在。如果不存在繼續用同樣的方法用第二個模式匹配。例如,路徑如下:
?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua
調用require "lili"時會試着打開這些文件:
lili
lili.lua
c:\windows\lili
/usr/local/lua/lili/lili.lua
require關注的問題只有分號(模式之間的分隔符)和問號,其他的信息(目錄分隔符,文件擴展名)在路徑中定義。
為了確定路徑,Lua首先檢查全局變量LUA_PATH是否為一個字符串,如果是則認為這個串就是路徑;否則require檢查環境變量LUA_PATH的值,如果兩個都失敗
require使用固定的路徑(典型的"?;?.lua")
require的另一個功能是避免重復加載同一個文件兩次。Lua保留一張所有已經加載的文件的列表(使用table保存)。如果一個加載的文件在表中存在require簡單的返回;
表中保留加載的文件的虛名,而不是實文件名。所以如果你使用不同的虛文件名require同一個文件兩次,將會加載兩次該文件。比如require "foo"和require "foo.lua",
路徑為"?;?.lua"將會加載foo.lua兩次。我們也可以通過全局變量_LOADED訪問文件名列表,這樣我們就可以判斷文件是否被加載過;同樣我們也可以使用一點小技巧讓
require加載一個文件兩次。比如,require "foo"之后_LOADED["foo"]將不為nil,我們可以將其賦值為nil,require "foo.lua"將會再次加載該文件。
一個路徑中的模式也可以不包含問號而只是一個固定的路徑,比如:
?;?.lua;/usr/local/default.lua
這種情況下,require沒有匹配的時候就會使用這個固定的文件(當然這個固定的路徑必須放在模式列表的最后才有意義)。在require運行一個chunk以前,它定義了
一個全局變量_REQUIREDNAME用來保存被required的虛文件的文件名。我們可以通過使用這個技巧擴展require的功能。舉個極端的例子,我們可以把路徑設為
"/usr/local/lua/newrequire.lua",這樣以后每次調用require都會運行newrequire.lua,這種情況下可以通過使用_REQUIREDNAME的值去實際加載required的文件。