2016-01-22 22 views
5

Bir işlevin dönüş biçimini almakla ilgileniyorum. ÖrneğinLua - Herhangi bir geri dönüşü nasıl alabilirim?

function foo() 
    return 1 
end 

local result = foo() -- foo is numeric 1 

function foo() 
    return {1,2,3} 
end 
local result1, result2, result3 = foo() 
local result = foo() -- this is bad as result is `1` but `2` and `3` are lost 

function foo() 
    return 1, 2, 3 
end 
local result = foo() -- foo is a table with all the numbers, that's ok 

Ben vekil fonksiyonları ile işlevlerini üzerine yazar bir profil oluşturucu inşa ediyorum ama veri, daha sonra bunun type() ve erişim accordingly` kontrol döndürülen bilmemiz gerekir ama koddan benim görülebilir 3 durumu tek bir yöntemle erişemiyorum. Var mı getiriler sayısı biliniyorsa

+0

@NicolBolas gibi çalışması gerekir()' işlevi ben foo' 'her üç vaka ele geçirmek istediğini açık olmalıdır. Lütfen burada herhangi bir teğet gerekli değildir. –

+0

@NicolBolas Yardımın için teşekkürler :) Soruyu güncelledim, umarım artık daha net görüş bildirirsiniz –

+0

Bu yüzden işlevin asıl arayanı sensin. Bu sonuçları kontrol etmeyi düşünüyor musunuz, sonra onları sanki "foo" gibi mi yapıyorsunuz? –

cevap

8

,

v1,v2,v3 = foo() 

gibi bir şey kullanmak ancak foo sonuncusu olan nil ile, iki değere ya da üç döndü olmadığını söylemek mümkün olmayacaktır.

sağlam bir çözüm, bir tablodaki tüm döner toplamak için:

v = table.pack(foo()) 

sonra v.n tüm nils dahil olmak üzere geri değerleri sayısını içerir.

+4

Table.pack'in Lua 5.2+ –

+4

gerektirdiğini unutmayın. Lua 5.2, 4 yıl önce yayınlandığından beri, Lua 5.1'i desteklemeyen LuaJIT'i kullanmıyorsanız, bu işlem tamamdır. – lhf

+0

İstediğim şey bu! Teşekkürler! –

4

Herhangi bir Lua sürümü 5.1+ üzerinde çalışan bir sürümü. WrapAndInspect ne yapar

local function WrapAndInspect(Inspector, FunctionToCall) 
    local function Inspect(...) 
     Inspector(...) 
     return ... 
    end 
    local function Wrapper(...) 
     return Inspect(FunctionToCall(...)) 
    end 
    return Wrapper 
end 

sonra, verilen işlevi çağırmak sağladığınız ikinci işlevine geri dönüş değerlerini geçecek bir fonksiyon oluşturur olduğunu. Bu işlev, üzerinde gerekli hissettiğiniz işlemleri yapar. Ancak çerçeve, orijinal işlevin dönüş değerlerinin oldukları gibi geçmesini sağlayacaktır. İşte

benzer bir şey yapar varyasyonu olan, ancak bunun yerine FunctionToCall sarılması, bu (parametreleriyle birlikte) çağrılacak bir işlev alır bir işlev verir:

local function CallAndInspect(Inspector) 
    local function Inspect(...) 
     Inspector(...) 
     return ... 
    end 
    local function Caller(FunctionToCall, ...) 
     return Inspect(FunctionToCall(...)) 
    end 
    return Caller 
end 

Bunu kullanabilirsiniz incelemek istediğiniz herhangi bir özel fonksiyon üzerinde.

3

table.pack'a erişimi olmayanlar için bir geçici çözüm. Bana göre basit ve lua 5.1 ve üstü - ve hatta daha eski versiyonlar üzerinde çalışmalı. Ben foo `üç örneğini verdik olarak

table_pack

table.pack

function table_pack(...) 
    return {n=select("#", ...), ...} 
end 
function foo() 
    return 1, 2, 3 
end 

local v = table_pack(foo()) 
print(v.n) 
+1

'...' tüm argümanlara genişletilmiş son gelmelidir, yani '{n = select (" # ", ...), ...}' daha iyi çalışıyor! – siffiejoe

+0

@siffiejoe Herhangi bir gerçek fark olup olmadığını merak ediyorum. Bu kodu lua 5.3'te test ettim. Gerçekte "daha iyi çalışır" diye bir durum var mı? – Rochet2

+2

Orada * gerçek bir fark: kodunuz sadece bir argüman için çalışır. Yukarıdaki örnek kodunuza i = 1, v.n baskı (i, v [i]) sonu 'ifadelerini ekleyerek kontrol edebilirsiniz. Lua el kitabından [alıntı] (http://www.lua.org/manual/5.3/manual.html#3.4.9) için: Listedeki son alanın form exp'i varsa ve ifade bir işlev çağrısıysa veya bir vararg ifadesi, bu ifadeyle döndürülen tüm değerler ardı ardına listeye girer (bkz. §3.4.10). '...', tablo yapıcısındaki son ifade değil, bu yüzden bir değere ayarlandı. – siffiejoe

İlgili konular