[lua] 你所不知道的lua nil值在可變參數函數中怎么處理!


在lua中,

  問題1:如果你在可變參數...中傳入若干個參數,其中有的參數要帶nil,這時怎么解決呢?比如local function _test(...) end    _test(1, nil, 3))

  問題2:更甚於在一個帶可變參數的函數里返回值是一個帶可變參數的尾調用,這時還能正確得到要的參數?(比如 local function _test2(...) return function(...) end end  _test2(4, nil, 6))


 接下來幾行大致過下基礎知識:

lua中nil是代表無(這不是廢話嗎?別急,往下看):

--比如:
local a = 10
a = nil
print(a)
--這時輸出的a是nil
  
--再比如:
local a = {1, nil, 3, 4}
for k, v in pairs(a) do
   print(k, '=', tostring(v))
end
--這時輸出的是
1    =    1
3    =    3
4    =    4
--也就是跳過了第二個為nil的鍵值對

 先來解決問題1,看這個例子:

local function _test(...)
    local paramCount = select('#', ...)
    local printStr = ''
    for i = 1, paramCount do
        local v = select(i, ...)
        printStr = printStr..i..'='..tostring(v)..', '
    end
    print(printStr)
end
_test(1, nil, 2, 3)
--輸出為: 1=1, 2=nil, 3=2, 4=3

上面可以看到正確地拿到了nil參數,它確實是在第2位的;主要就是利用select函數取到可變參數的總個數,如果你是要在_test(...)函數中將可變參數保存下來,然后在適當的時機再傳到其他的函數中,則需要按下面這種方式:

local paramT
local function _test(...)
    paramT = {paramCount=select('#', ...), ...}
end
local function _receiveArg(...)
    local paramCount = select('#', ...)
    local printStr = ''
    for i = 1, paramCount do
        local v = select(i, ...)
        printStr = printStr..i..'='..tostring(v)..', '
    end
    print(printStr)
end
_test(1, nil, 2, 3)
_receiveArg(unpack(paramT, 1, paramT.paramCount))
--同樣地輸出: 1=1, 2=nil, 3=2, 4=3, 

主要就是使用unpack函數,把參數表paramT解包作為參數傳過去,但要注意指定參數對應的索引范圍是1~paramT.paramCount,特別的paramT.paramCount這個是存放在table中的hash部分,所以不受影響;


 最后解決問題2,看這個例子:

local function _receiveArg(...)
    local paramCount = select('#', ...)
    local printStr = ''
    for i = 1, paramCount do
        local v = select(i, ...)
        printStr = printStr..i..'='..tostring(v)..', '
    end
    print(printStr)
end
local function _test2(func, ...)
    local paramT = {...}
    local paramCount = select('#', ...)
    return function(...)
        local callbackParamCount = select('#', ...)
        for i = 1, callbackParamCount do
            paramT[paramCount + i] = select(i, ...)
        end
        return func(unpack(paramT, 1, paramCount + callbackParamCount))
    end
end
local func = _test2(_receiveArg, 10, nil, 30)
func(nil, 40, nil, 50)
--輸出:1=10, 2=nil, 3=30, 4=nil, 5=40, 6=nil, 7=50, 

主要看_test2(func, ...)這個函數里中的function(...)尾調用的處理!里面是合並了_test2函數的可變參數列表與這個尾調用的可變參數列表!並最后順序把參數原封不動地return。


大致就這些,題外話:現在在我們的游戲里使用lua就上面這樣的寫法,原先想用coroutine替換掉這些回調(尾調用),因為之前就是碰到可變參數里帶nil值的情況無法正確的處理!(用谷歌搜索了一些博文,但都沒提到我想要的解決方案)最后還是在stackoverflow(見這個網址:http://stackoverflow.com/questions/7183998/in-lua-what-is-the-right-way-to-handle-varargs-which-contains-nil)看了unpack的正確用法(得到了啟發)歸根結底還是沒先去看官方文檔中select與unpack函數的正確用法導致!!所以上述的是實現方式是我花了一點時間(想)通后實現的!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM