編譯
- lua 是解釋語(yǔ)言
- 但 lua 允許在運(yùn)行源代碼前,先將源代碼編譯為一種中間形式
- 區(qū)別解釋語(yǔ)言的主要特征并不在于是否能編譯它們
- 在于編譯器是否是語(yǔ)言運(yùn)行時(shí)庫(kù)的一部分
- 是否有能力執(zhí)行動(dòng)態(tài)生成的代碼
loadfile 函數(shù)
-
dofile
函數(shù)是一種內(nèi)置的操作槐脏,用于運(yùn)行 lua 代碼塊 -
dofile
僅是做了loadfile
的輔助工作
-
loadfile
會(huì)從一個(gè)文件加載 lua 代碼塊 - 但不會(huì)運(yùn)行代碼潭千,只是編譯代碼
- 然后將編譯結(jié)果作為一個(gè)函數(shù)返回
-
dofile
會(huì)引發(fā)錯(cuò)誤 -
loadfile
只會(huì)拋出錯(cuò)誤值,但不處理錯(cuò)誤
function dofile(filename)
-- assert 返回錯(cuò)誤值
local f = assert(loadfile(filename))
return f()
end
- 發(fā)生錯(cuò)誤時(shí)对人,
loadfile
會(huì)返回nil
及錯(cuò)誤消息允跑,可自定義錯(cuò)誤消息 - 在需要多次運(yùn)行一個(gè)文件時(shí),只需調(diào)用一次
loadfile
获雕,多次調(diào)用它的返回結(jié)果,也就是那個(gè)函數(shù)即可 - 而
dofile
開銷則相比loadfile
大得多轿偎,因?yàn)?loadfile
只編譯一次文件
loadstring 函數(shù)
- 從一個(gè)字符串中讀取代碼
- 同樣會(huì)返回一個(gè)函數(shù)
- 開銷很大典鸡,因?yàn)樵?strong>每次調(diào)用
loadstring
時(shí)都會(huì)編譯一次 - 而
function
的寫法只在編譯對(duì)于程序塊時(shí)被編譯了一次
i = 0
f = loadstring("i = i + 1") -- 等效于 f = function() i = i + 1 end
f()
print(i) -- 1
f()
print(i) -- 2
-- dostring 完成加載并運(yùn)行代碼
assert(loadstring(s))() -- 語(yǔ)法錯(cuò)誤 "attempt to call a nil value"
-
loadstring
編譯時(shí)不涉及詞法域 -
loadsting
只在全局環(huán)境中編譯字符串,而非局部環(huán)境
i = 32
local i = 0
f = loadstring("i = i + 1; print(i)")
g = function() i = i + 1; print(i) end
f() -- 33 使用了全局變量
g() -- 1 使用了局部變量
- 可以執(zhí)行外部代碼
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
,有一個(gè)真正的原始函數(shù)load
-
loadfile
和loadstring
分別從文件和字符串中讀取程序塊 -
load
接收一個(gè)「讀取器函數(shù)」坏晦,并在內(nèi)部調(diào)用它來(lái)獲取程序塊 - 讀取器函數(shù)可以分幾次返回一個(gè)程序塊萝玷,
load
會(huì)反復(fù)調(diào)用它,直到它返回nil
(表示程序塊結(jié)束)為止 - 只有當(dāng)程序塊不在文件中昆婿,或者程序塊過(guò)大而無(wú)法放入內(nèi)存時(shí)球碉,才會(huì)用到
load
- lua 將所有獨(dú)立的程序塊視為一個(gè)匿名函數(shù)的函數(shù)體,并且該匿名函數(shù)還具有可變長(zhǎng)實(shí)參
- 與其他函數(shù)一樣仓蛆,程序塊中可以聲明局部變量
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 函數(shù)不會(huì)引發(fā)錯(cuò)誤。在錯(cuò)誤發(fā)生時(shí),
load
會(huì)返回nil
以及一條錯(cuò)誤信息
print(loadstring("a a"))
-- nil [string "a a":1 '=' expected nead 'a']
-
loadfile
和loadstring
不會(huì)帶來(lái)任何副作用 - 它們只是將程序塊編譯為一種中間表示豆拨,然后將結(jié)果作為一個(gè)匿名函數(shù)來(lái)返回直奋。
- 而并不是加載了一個(gè)程序塊,或定義了其中的函數(shù)
- 函數(shù)定義是一種賦值操作施禾,是在運(yùn)行時(shí)才完成的操作脚线。
-- 編寫一個(gè) lua 文件,命名為 foo
function foo(x)
print(x)
end
-- 在 cmd 中的 lua 解釋器中輸入
f = loadfile("你存放 foo 文件的路徑")
print(foo()) -- nil
f() -- 定義函數(shù)
foo("test") -- test
- 執(zhí)行外部代碼的一些操作
- 處理加載程序塊時(shí)報(bào)告任何錯(cuò)誤
- 如果代碼不受信任弥搞,需要在保護(hù)環(huán)境(即之前提到的「沙盒」中執(zhí)行這些代碼)
本篇文章由一文多發(fā)平臺(tái)ArtiPub自動(dòng)發(fā)布