編譯
- lua 是解釋語言
- 但 lua 容許在運行源代碼前,先將源代碼編譯爲一種中間形式
- 區別解釋語言的主要特徵並不在因而否能編譯它們
- 在於編譯器是不是語言運行時庫的一部分
- 是否有能力執行動態生成的代碼
loadfile 函數
-
dofile
函數是一種內置的操做,用於運行 lua 代碼塊git -
dofile
僅是作了loadfile
的輔助工做github -
loadfile
會從一個文件加載 lua 代碼塊express -
但不會運行代碼,只是編譯代碼函數
-
而後將編譯結果做爲一個函數返回lua
-
dofile
會引起錯誤spa -
loadfile
只會拋出錯誤值,但不處理錯誤code
function dofile(filename) -- assert 返回錯誤值 local f = assert(loadfile(filename)) return f() end
- 發生錯誤時,
loadfile
會返回nil
及錯誤消息,可自定義錯誤消息 - 在須要屢次運行一個文件時,只需調用一次
loadfile
,屢次調用它的返回結果,也就是那個函數便可 - 而
dofile
開銷則相比loadfile
大得多,由於loadfile
只編譯一次文件
loadstring 函數
- 從一個字符串中讀取代碼
- 一樣會返回一個函數
- 開銷很大,由於在每次調用
loadstring
時都會編譯一次 - 而
function
的寫法只在編譯對於程序塊時被編譯了一次
i = 0 f = loadstring("i = i + 1") -- 等效於 f = function() i = i + 1 end f() print(i) -- 1 f() print(i) -- 2 -- dostring 完成加載並運行代碼 assert(loadstring(s))() -- 語法錯誤 "attempt to call a nil value"
loadstring
編譯時不涉及詞法域loadsting
只在全局環境中編譯字符串,而非局部環境
i = 32 local i = 0 f = loadstring("i = i + 1; print(i)") g = function() i = i + 1; print(i) end f() -- 33 使用了全局變量 g() -- 1 使用了局部變量
- 能夠執行外部代碼
do print("enter you expression:") local l = io.read() local func = assert(loadstring("return '" .. l .. "'")) print("the value of your expression is " .. func()) end do print("enter function to be plotted(with variable 'x'):") local l = io.read() local f = assert(loadstring("return " .. l)) for i = 1, 20 do x = i print(x .. ":" .. string.rep("*", f())) end end
-
loadfile
和loadstring
,有一個真正的原始函數load
ip -
loadfile
和loadstring
分別從文件和字符串中讀取程序塊內存 -
load
接收一個「讀取器函數」,並在內部調用它來獲取程序塊字符串 -
讀取器函數能夠分幾回返回一個程序塊,
load
會反覆調用它,直到它返回nil
(表示程序塊結束)爲止 -
只有當程序塊不在文件中,或者程序塊過大而沒法放入內存時,纔會用到
load
-
lua 將全部獨立的程序塊視爲一個匿名函數的函數體,而且該匿名函數還具備可變長實參
-
與其餘函數同樣,程序塊中能夠聲明局部變量
loadstring("a = 1") -- 等效於 function(...) a = 1 end f = loadstring("local a = 10; print(a + 10)") f() -- 20
- 重寫讀取輸入示例,避免使用全局變量 x
print("enter function to be plotted (with variable 'x'):") local l = io.read() local f = assert(loadstring("local x = ...; return " .. l)) for i = 1, 20 do print(string.rep("*", f(i))) end
- load 函數不會引起錯誤。在錯誤發生時,
load
會返回nil
以及一條錯誤信息
print(loadstring("a a")) -- nil [string "a a":1 '=' expected nead 'a']
loadfile
和loadstring
不會帶來任何反作用- 它們只是將程序塊編譯爲一種中間表示,而後將結果做爲一個匿名函數來返回。
- 而並非加載了一個程序塊,或定義了其中的函數
- 函數定義是一種賦值操做,是在運行時才完成的操做。
-- 編寫一個 lua 文件,命名爲 foo function foo(x) print(x) end -- 在 cmd 中的 lua 解釋器中輸入 f = loadfile("你存放 foo 文件的路徑") print(foo()) -- nil f() -- 定義函數 foo("test") -- test
- 執行外部代碼的一些操做
- 處理加載程序塊時報告任何錯誤
- 若是代碼不受信任,須要在保護環境(即以前提到的「沙盒」中執行這些代碼)
本篇文章由一文多發平臺ArtiPub自動發佈