彼德·舒克

lua-users home
wiki

我是一位 C/Awk/Perl 駭客,不太喜歡 Perl 中大量晦澀難懂的函數和巨集,稱為 XS。這一點以及 Perl 的龐大規模讓我不再使用 Perl 而改用 Lua。雖然自從我改用 Lua 之後,Perl 的擴充工具和文件已有所進步,但我不會再回到 Perl,因為 Lua 真的是一款令人樂於使用的語言。

範例 Lua 程式碼

範例 C++ 程式碼

範例 C 程式碼

十六進位數字補丁 [1]

Lua 可使用 tonumber 函數處理十六進位數字,但我的同事比較習慣使用 C 的 0x 語法,所以,我為他們製作了這個補丁。

此補丁適用於 5.0,但它非常簡單,你可以輕鬆地讓它適用於舊版的 Lua。lua-5.1-alpha 版本 [2]

$ lua
Lua 5.0  Copyright (C) 1994-2003 Tecgraf, PUC-Rio
> = 0x10
16
> = 0x100
256
> function hex(n)
>>   return tonumber(n,16)
>> end
>
> = 0xff == hex'FF'
true
>

讀取目錄補丁 [3]

此補丁新增 chdiropendirstatos 函數表。它適用於 Linux、Cygwin 和 Mingwin。

與 Ruby 類似的語法糖

對於不喜歡一直輸入 self.member 的人來說,以下是 [lauxlib.c] 的一個版本,它將 luaL_loadfileluaL_loadbuffer 改為將 @somename 取代為 self.somename,並將 @somemethod(...) 取代為 self:somemethod(...)

你也可以使用 # 作為註解。

List = setmetatable({}, {__index = table})
List.__index = List

function List:new(...) return setmetatable(arg, self) end
function List:push(x) @insert(x) return self end
function List:pop() return @remove() end
function List:shift() return @remove(1) end
function List:append(list)
  for _,elem in ipairs(list) do @insert(elem) end
  return self
end

function List:fun(a, b)
  @a = a
  @b = b
  return @n
end

x = List:new(1, 2, 5)
x:foreachi(print)
x:push(99)
print(x:concat', ')
print('fun', x:fun('one', 'two'), x:shift())
x:foreach(print)
以下是上述範例的輸出。
$ lua eg.lua
1       1
2       2
3       5
1, 2, 5, 99
fun     4       1
1       2
2       5
3       99
a       one
b       two
n       3 

預設為局部變數

對於有 Python 或 PHP 背景的人來說,可能比較希望函數中的變數在預設情況下為局部變數。這很容易在 Lua 5.0 中完成,只要在函數儲存在套件中時,使用 newindex 事件來讓函數擁有新的環境即可。

例如

local Pkg = {}

local function fixfuncs(env, name, value)
  rawset(env, name, value)
  if type(value)=='function' then
    print('newfunction', env, name, value)
    setfenv(value, setmetatable({}, {__index=env}))
  end
end

setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newindex=fixfuncs}))

y = 0

function one(x)
  y = x
  return y
end

function two()
  Pkg.y = 99
  y = 2
  return y
end

local function three()
  y = 3
  return y
end

print(y, one(1), y, two(), y, three(), y)
以上程式碼應該會輸出以下內容
$ lua test1.lua
newfunction     table: 0xa0459f0        one     function: 0xa046ab8
newfunction     table: 0xa0459f0        two     function: 0xa0466d8
0       1       0       2       99      3       3
如果想要存取套件或全域範圍內的變數,你必須在變數前面加上 Pkg._G. 前綴。newindex 事件不會對局部函數生效,但是,如果你不是 Perl 程式設計師,你可能不在乎這一點。

新函數表和函數補丁 [4]

如果您想神奇地改變 local 函數的功能環境呢?這裡有一個可疑的修補程式,添加了 newfunctionnewtable 事件。當在 metatable 中具有 __newfunction 鍵的環境中建立函數時,就會呼叫 newfunction 事件的元方法。

我們可以這樣改寫先前的範例

local Pkg = {}

local function fixfuncs(env, f)
  print('newfunction', env, f)
  setfenv(f, setmetatable({}, {__index=env}))
end

setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newfunction=fixfuncs}))

y = 0

function one(x)
  y = x
  return y
end

function two()
  Pkg.y = 99
  y = 2
  return y
end

local function three()
  y = 3
  return y
end

print(y, one(1), y, two(), y, three(), y)
現在甚至函數 threey 變數也變成了 local。
$ lua test2.lua
newfunction     table: 0xa0459f0        function: 0xa045fb0
newfunction     table: 0xa0459f0        function: 0xa046478
newfunction     table: 0xa0459f0        function: 0xa040730
0       1       0       2       99      3       99

孤立方法修補程式 [5]

此修補程式會改變 object:method() 的語義,改用新的單獨 self 事件,而不是一般會使用的 index 事件。這讓您可以在表格中新增一些類別,而且仍然可以保留 index 事件供其他用途使用。

local Pkg = {}

local function fixtable(env, t)
  print('newtable', env, t)
  setmetatable(t, {__self=table})
end

setfenv(1, setmetatable(Pkg, {__index=getfenv(), __newtable=fixtable}))

t = { 'one', 'two', 'three' }

print(t:concat'/', t:getn(), t:remove(1), t:remove(), t:getn())
以下是此範例的輸出
$ lua test3.lua
newtable        table: 0xa0459f0        table: 0xa045f98
one/two/three   3       one     three   1

適用於 Coldfire 5282 的 Lua

以下是一個可使用 m68k-elf-gcc 編譯的 tar 檔案 [6]

來自修正檔 [7]

以下是一個修正檔,可讓您從表格值中解壓縮命名值,因此您可以執行類似這樣的動作

$ src/lua
Lua 5.1 (alpha)  Copyright (C) 1994-2005 Lua.org, PUC-Rio
> write from io
> format from string
>
> function printf(...) write(format(...)) end
>
> printf("I should have written this patch %d years ago\n", 2)
I should have written this patch 2 years ago
>

以下是此修正檔的基本版本,其中使用現有的關鍵字 in 而不是 from [8]


近期變更 · 喜好設定
編輯 · 歷程記錄
最後編輯時間為 2020 年 11 月 25 日上午 3:15 GMT (差異)