**
今天同事提了個需求,他希望可以給部分 lua **(由策劃編寫)做乙個沙盒關起來。在 lua 裡做沙盒很容易,只需要控制函式的環境就可以了。不過另乙個附加需求是,這些**還可以直接利用 require 載入。
而我們又不想去修改系統的 api 介面,那麼怎麼做到這點呢?
首先, 我希望使用的時候看起來像這樣:
local *** = require "***" (myenv)和傳統的 require 用法不同,可以在後面追加乙個引數 myenv 。這樣的話,每次 *** 模組被 require 時,它其實被重複執行一次,但會繫結不同的
_env
。
其次,既然模組會被反覆初始化,那麼我們甚至還可以約定,每個這種沙盒封裝的模組還可以接收 require 的傳入的額外引數。
做到這點很容易,我們只需要在 package.searchers 裡追加乙個自定義的 loader 然後並不返回載入的模組 chunk ,而是做乙個函式封裝。將 chunk 的執行推遲到傳入 myenv 呼叫之後。
這樣,load chunk 本身還是依靠 require 的 package 機制快取**的,只是每次呼叫後,重新繫結_env
生成了一組新例項。
我在 gist 上貼了一組**實現這個特性:延遲繫結環境的 require 。
mymod.user.lua
local m ={}function
m.test(...)
(...)
endreturn m
requirenv.lua
local package =packagelocal debug =debug
local
function
load_env(filename)
local f,err = loadfile
(filename)
if f == nil
then
return
err
endreturn
function
()
return
function
(env)
if env then
debug.setupvalue(f, 1
, env)
endreturn
f(filename)
endend
endlocal
function
searcher_env(name)
local filename, err =package.searchpath(name, package.upath)
if filename == nil
then
return
err
else
return
load_env(filename)
endend
table.insert(package.searchers, searcher_env)
test.lua
require"requirenv
"package.upath = "
./?.user.lua
"local myprint = print
local env =
local s = require
"mymod
"(env)
s.test
"hello world"--
hook hello world
設計模式 行為擴充套件
訪問者模式 表示乙個作用於某物件結構中各元素的操作。它讓我們可以在不改變各元素的前提下定義作用於這些元素的新操作 使用場景 1.乙個複雜的物件結構包含很多其它物件,它們有不同的介面,但是相對這些物件實施一些依賴於其具體型別的操作 2.需要對乙個組合結構中的物件進行許多不相關的操作,但是不想讓這些操作...
vim中lua require路徑的gf跳轉
vimrc中配置如下 path指定查詢的路徑,詳情help path includeexpr是嘗試替換路徑名中的.為 詳情help includeexpr suffixesadd為嘗試路徑字尾,詳情help suffixesadd set path usr include,lualib,work,s...
物件的行為
建構函式 是乙個特殊函式,該函式將在建立物件時執行,該函式返回類i型固定為該類的型別。若沒有手動書寫建構函式,編譯器會使用預設的建構函式,預設建構函式無參無函式體 建構函式宣告語法 訪問修飾符 類名 形參列表 函式體 建構函式的呼叫語法 new 類名 實參列表 呼叫建構函式即建立新的物件 函式過載 ...