2015-06-09 20 views
6

E 'possibile ottenere la dimensione di una funzione in byte per vedere se corrisponde ad un'altra funzione simile all'operatore sizeof C++, o valutare due funzioni in un altro modo per vedere se sono entrambe uguali senza sapere realmente quale funzione/s siamo? Esempio:Lua - È possibile verificare se 2 funzioni sono uguali?

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

Se ciò non è possibile, basta dire e soddisferà la mia risposta! Grazie!

MODIFICA: Il corpo di una funzione è quello che devo verificare per vedere se è uguale al corpo di un'altra funzione. Il riferimento in memoria sarà diverso, quindi non posso usare "==" ma il nome di riferimento della funzione può essere diverso.

+0

Le funzioni 'f (x) restituiscono x + 1 end' e' function g (x) restituiscono x + 1 end' uguale? –

+0

Sì e questo funzionerebbe. Il riferimento chiave f e g in realtà non importa. Stavo solo cercando un modo per verificare se il corpo è uguale. – Mayron

+1

Quindi è impossibile a meno che tu non abbia la fonte. Una funzione potrebbe essere caricata dal codice by.e. –

risposta

5

L'utilizzo di == per le funzioni controlla solo se fanno riferimento alla stessa funzione, che non è quello che ci si aspettava.

Questo compito è piuttosto difficile, se non impossibile. Per i casi molto semplici, ecco un'idea:

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

f e g sono due funzioni che sono uguali per la sua definizione. Supponendo che il file è t.lua, eseguire:

luac -l t.lua 

L'output è:

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 

Come si può vedere, le due funzioni hanno le stesse istruzioni della macchina virtuale.

+0

Grazie per la spiegazione. Penso che sia il più vicino che otterrò. Peccato non c'è modo più semplice, ma dovrò farlo :) – Mayron

+2

Se l'accesso al bytecode ti avvicina a una soluzione, c'è [lbci] (http://webserver2.tecgraf.puc-rio.br/~lhf/ftp/lua/# lbci), una libreria di controllo bytecode (per Lua 5.1 e 5.2, installabile anche tramite LuaRocks) scritta da @lhf, che potrebbe darti le stesse informazioni di 'luac -l' sopra. – siffiejoe

5

Il confronto con il bytecode è?

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

Sicuramente, ci sarebbero alcuni casi in cui i precedenti non avrebbero funzionato. Ad esempio:

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 

Entrambe le funzioni fanno la stessa cosa, ma generano un bytecode diverso. Forse se dichiari ciò che stai cercando di ottenere, può essere fornita una soluzione migliore rispetto al confronto delle funzioni.

+0

Ci scusiamo per la risposta lenta. Devo verificare se due tabelle sono identiche, in modo che vengano aggiunte solo nuove voci a una tabella se non appaiono in un'altra tabella e posso facilmente confrontare se un valore è già in un'altra tabella ma le funzioni sono molto più complicate come == solo confronti indirizzi di memoria. – Mayron

+0

'string.dump' fallirebbe anche per questo:' function a() end' 'function b() end'' print (string.dump (a) == stringa.dump (b))' Outputs 'false' . –

+0

È necessario eliminare le informazioni di debug dai dump prima di confrontare: 'string.dump (f1, true) == string.dump (f2, true)'. Funziona perfettamente con LuaJIT (ma per qualche motivo non funziona su Lua 5.3). –

Problemi correlati