0x07編譯、執行與錯誤
Lua雖然是一種解釋性語言,但Lua允許在運行源碼前,先將源碼預編譯成一種中間形式。
1.編譯與執行
Lua提供了dofile
loadfile
兩個接口來從文件里加載Lua的代碼塊,但它不會運行代碼,而只是編譯做對,然後將編譯結果作爲一個函數返回
function dofile (filename)
local f = assert(loadfile(filename))
return f()
end
注:如果dofile
失敗,那麼其中的assert
就會引發一個錯誤
loadstring
與loadfile
類似,但是不同的一點是,loadfile
是對一個文件進行讀取的而loadstring
是對一個字符串來進行讀取的。
loadstring功能非常的強大,但應該謹慎使用,因爲他是一個開銷較大的函數
f = loadstring("i = i + 1") --Code 1
上面的代碼等價於下面的代碼
f = function() i = i + 1 end --Code 2
- Code1 和 Code2的代碼是類似的,但是Code2的代碼會快很多,因爲它只在編譯對應程序塊時被編譯了一次。而Code1卻在每次調用
loadstring()
時都被重新編譯。 - Code1與Code2嚴格來說是不等價的,因爲loadstring在編譯時不涉及詞法域
i = 32
local i = 0
f = loadstring("i = i + 1; print(i)")
g = function() i = i + 1; print(i) end
f() -->33
g() -->1
loadstring
最大的用處是用來處理來自外部輸入的代碼,如用戶自定義的程序
匿名函數
Lua將所有獨立的程序塊視爲一個匿名函數的函數體,並且該匿名函數還具有可變長實參。例如loadstring(“a=1”)返回的結果等價於以下表達式:
function(...) a = 1 end
loadstring
loadfile
對傳入的參數編譯後將結果作爲一個匿名函數返回。
如有一個foo.lua文件:
function foo (x)
print(x)
end
然後執行下面的代碼:
f = loadfile("foo.lua")
在此之後,函數完成編譯,但是還沒定義它。
print(foo) -->nil
f() -->定義了foo
foo("ok") -->ok
其它:loadlib函數加載指定的庫,並將其直接鏈接入Lua
2.錯誤及錯誤處理
由於Lua是一種擴展語言,通常嵌入在應用程序中,因此在發生錯誤時它不能簡單地崩潰或者退出
通過error
來處理錯誤
print "enter a number:"
n = io.read("*number")
if not n then error("invalid input") end
--或者使用assert
--n = assert(io.read("*number"), "invalid input")
當一個行爲發生異常時,通常有兩種處理方法:1.返回錯誤代碼(通常是nil) 2.引發一個錯誤(調用error
)
如果需要在Lua中處理錯誤,則必須使用函數pcall
來包裝需要執行的代碼
function foo()
<some code>
<some code> print(a[i]) --潛在的錯誤:a爲需要打印的錯誤信息
<some code>
end
然後用pcall
調用foo
:
if pcall(foo) then
--執行時沒有發生錯誤
<正常代碼>
else
--foo發生錯誤,處理異常
<錯誤處理代碼> end