2011-08-25 21 views
19

İlk bağımsız değişken olarak bir dosya tanıtıcısı alan bir hata ayıklama yazdırma işlevi oluşturmaya çalışıyorum. Ben argümanlar içinde nil değeri geçemiyor gibi bu işlev sürece çalışırLua'da, nil içeren varargs işlemek için doğru yolu nedir?

function fprint (f, ...) 
    for i, v in ipairs{...} do 
     f:write(tostring(v)) 
     f:write("\t") 
    end 
    f:write("\n") 
end 

: Birincisi, böyle bir işlevi yazın. Ancak bunu nil ile çağırırsam, nil değerini ve argümanların kalanını yazdırmaz.

fprint(io.stderr, 1, 2, nil, 3) 
=> prints only 1 and 2 

Peki, bu sorunu düzeltmenin doğru yolu nedir?

cevap

26

Aslında, varargs içinde nil değerlerini işlemek kolaydır, tek ihtiyacınız bile nil ile çalışır select işlevini kullanmaktır (bu parametrelerin gerçek sayısını sayar).

function vararg(...) 
    local args = table.pack(...) 
    for i=1,args.n do 
     -- do something with args[i], careful, it might be nil! 
    end 
end 
: sadece bu kullanımı parametre sayısı için, bu yüzden, bu alanda n depolanır
function table.pack(...) 
    return { n = select("#", ...), ... } 
end 

içlerinden yineleme: Aşağıdaki deyim Lua 5.2 bir çekirdek kütüphane işlevi table.pack olduğu kadar yararlıdır
+1

Tatlı! Seçimi bilmiyordum. – torus

+2

En kullanışlı eklenti, artık tabloyu açamazsınız. Ambalajı açmak için: 'local tbl = {n = select (" # ", ...), ...}; yazdır (paketten (tbl, 1, tbl.n)); ' – Aidiakapi

+0

Bu cevap resmi wiki'de ayrıntılı olarak tartışıldı: http://lua-users.org/wiki/VarargTheSecondClassCitizen –

2

bildiğim en iyi olarak, # işlemi nil izler herhangi bir konuma işaret edebilir çünkü nil girdileri içeren bir dizinin uzunluğunu bilmek kolay uygulama bağımsız bir yol var, ama bu hızlı bir uygulama bağımlı bir çözümdür Bu nil yazdıracaktır. Eğer atlayabilirsiniz

function last_index(array) 
    local max = 0 
    for k, _ in pairs(array) do 
    max = math.max(max, k) 
    end 
    return max 
end 

function fprint (f, ...) 
    local parm={...} 
    for i=1,last_index(parm) do 
     f:write(tostring(parm[i])) 
     f:write("\t") 
    end 
    f:write("\n") 
end 

:

function fprint (f, ...) 
    local parm={...} 
    for i=1,#parm do 
     f:write(tostring(parm[i])) 
     f:write("\t") 
    end 
    f:write("\n") 
end 

Aksine # üzerinde geçişi daha size parm tablo bir dizidir biliyorum ve böyle bir şey kullanmak beri, sen karmaşık (ve dolayısıyla uygulama bağımsız) alabilirsiniz nil değerleri ve siparişi önemli değil, daha sonra pairs'a geçmek çok daha kolay olurdu.

+0

Teşekkürler! Çiftlere geçmeyi deneyeceğim. – torus

+0

Açıkçası Michael'ın cevabı en iyisi, kendimi bile + 1'ledim, ancak aşağı oy için başka bir sebep var mı? – BMitch

+0

Hayır. İki cevaptan ikisini de cevaplandırdım :) – torus

İlgili konular