2015-06-09 50 views
6

Czy możliwe jest uzyskanie rozmiaru funkcji w bajtach, aby sprawdzić, czy pasuje ona do innej funkcji podobnej do operatora size ++ C++, czy ocenić dwie funkcje w inny sposób, aby zobaczyć, czy oba są równe, bez faktycznego zrozumienia funkcji/funkcji są? Przykład:Lua - Czy można sprawdzić, czy 2 funkcje są równe?

local function equals(func1, func2) 
    -- check them and return true if equal 
end 

Jeśli nie jest to możliwe, po prostu powiedz i to zaspokoi moją odpowiedź! Dziękujemy!

EDYCJA: Ciało jednej funkcji jest tym, co muszę sprawdzić, aby sprawdzić, czy jest takie samo jak ciało innej funkcji. Odniesienie w pamięci będzie inne, więc nie mogę użyć "==", ale nazwa referencyjna tej funkcji może być inna.

+0

Czy 'funkcja f (x) zwraca x + 1 koniec' i' funkcja g (x) zwraca x + 1 koniec' jest równy? –

+0

Tak i to by działało. Kluczowe odniesienie f i g nie ma znaczenia. Po prostu szukałem sposobu na sprawdzenie, czy ciało jest równe. – Mayron

+1

To jest niemożliwe, chyba że masz źródło. Funkcja może być ładowana z kodu tektonicznego. –

Odpowiedz

5

Korzystanie z funkcji tylko sprawdza, czy odnoszą się do tej samej funkcji, co nie jest zgodne z oczekiwaniami.

Zadanie to jest raczej trudne, jeśli nie niemożliwe. Dla naprawdę prostych przypadkach, oto pomysł:

function f(x) return x + 1 end 
local g = function(y) return y + 1 end 

f i g są dwie funkcje, które są równe według definicji. Zakładając, że plik jest t.lua uruchom:

luac -l t.lua 

Wyjście jest:

main <t.lua:0,0> (4 instructions at 00000000003081c0) 
0+ params, 2 slots, 1 upvalue, 1 local, 1 constant, 2 functions 
     1  [1]  CLOSURE   0 0  ; 0000000000308330 
     2  [1]  SETTABUP  0 -1 0 ; _ENV "f" 
     3  [2]  CLOSURE   0 1  ; 0000000000308dc0 
     4  [2]  RETURN   0 1 

function <t.lua:1,1> (3 instructions at 0000000000308330) 
1 param, 2 slots, 0 upvalues, 1 local, 1 constant, 0 functions 
     1  [1]  ADD    1 0 -1 ; - 1 
     2  [1]  RETURN   1 2 
     3  [1]  RETURN   0 1 

function <t.lua:2,2> (3 instructions at 0000000000308dc0) 
1 param, 2 slots, 0 upvalues, 1 local, 1 constant, 0 functions 
     1  [2]  ADD    1 0 -1 ; - 1 
     2  [2]  RETURN   1 2 
     3  [2]  RETURN   0 1 

Jak widać, te dwie funkcje mają takie same instrukcje w maszynie wirtualnej.

+0

Dziękuję za wyjaśnienie. Myślę, że to tak blisko, jak to tylko możliwe. Szkoda, że ​​nie ma prostszego sposobu, ale muszę to zrobić :) – Mayron

+2

Jeśli dostęp do kodu bajtowego zbliży cię do rozwiązania, jest [lbci] (http://webserver2.tecgraf.puc-rio.br/~lhf/ftp/lua/# lbci), biblioteka inspektora kodu bajtowego (dla Lua 5.1 i 5.2, również instalowana przez LuaRocks) napisana przez @lhf, która mogłaby dać ci te same informacje co 'luac -l' powyżej. – siffiejoe

5

Czy porównamy kod bajtowy?

local function equals(func1, func2) 
    return string.dump(func1) == string.dump(func2) 
end 

Oczywiście, byłyby przypadki, w których powyższe zawiodło. Na przykład:

local function f1 (...) 
    local a = print 
    a(...) 
end 

local function f2 (...) 
    print(...) 
end 


local function equals (f1, f2) 
    return string.dump(f1) == string.dump(f2) 
end 

print(equals(f1,f2)) --> false 

Obie funkcje robią to samo, ale generują inny kod bajtowy. Może, jeśli określisz, co chcesz osiągnąć, można zaproponować lepsze rozwiązanie niż porównywanie funkcji.

+0

Przepraszamy za powolną odpowiedź. Muszę sprawdzić, czy dwie tabele są identyczne, tak że dodawane są tylko nowe wpisy do jednej tabeli, jeśli nie pojawiają się w innej tabeli i mogę łatwo porównać, czy wartość jest już w innej tabeli, ale funkcje są znacznie trudniejsze, ponieważ == porównuje tylko adresy pamięci. – Mayron

+0

'string.dump' zawodzi nawet w tym przypadku:' function a() end' 'function b() end'' print (string.dump (a) == string.dump (b)) 'Wyprowadza' false' . –

+0

Powinieneś usunąć informacje debugowania ze zrzutów przed porównaniem: 'string.dump (f1, true) == string.dump (f2, true)'. Działa doskonale na LuaJIT (ale z jakiegoś powodu nie działa na Lua 5.3). –