luaguides

rawequal

rawequal(value1, value2)

rawequal checks whether two values are exactly the same object in memory, bypassing any custom __eq metamethod. When you need to compare identity rather than value equality, this function is what you reach for.

Parameters

ParameterTypeRequiredDescription
value1anyYesFirst value to compare
value2anyYesSecond value to compare

rawequal returns true if value1 and value2 are identical objects (the same reference), and false otherwise. Unlike the == operator, it never invokes the __eq metamethod.

How It Differs From the == Operator

The == operator lets objects define their own equality behavior through the __eq metamethod. Two tables that are structurally identical but stored in different memory locations are considered unequal by == unless their __eq metamethod says otherwise. rawequal ignores metamethods entirely and checks whether the two values are the exact same object.

local a = {x = 1, y = 2}
local b = {x = 1, y = 2}

print(a == b)        -- false (different objects, same contents)
print(rawequal(a, b)) -- false (they are different objects)
print(rawequal(a, a)) -- true (same object compared to itself)

This distinction matters most when working with tables as keys, caching systems, or any code that relies on object identity rather than value equality.

Comparing Tables Used as Keys

If you use a table as a table key, Lua compares those keys by identity. rawequal reflects this exact behavior, letting you check whether two keys are the same object.

local key = {"important", "key"}
local cache = {}

cache[key] = "stored value"

print(cache[key])        -- "stored value"
print(rawequal(cache[key], "stored value")) -- false (comparing value, not key)

When iterating over a table’s raw keys with next, rawequal is useful for checking whether a particular key object is present.

Avoiding Infinite Recursion in __eq

When you define a custom __eq metamethod that compares objects, calling rawequal inside that metamethod avoids the risk of infinite recursion if the comparison logic itself involves equality checks.

local function deepEqual(a, b)
    if rawequal(a, b) then
        return true  -- same object, skip further comparison
    end
    -- ... comparison logic follows
    return false
end

Comparing Primitives

rawequal works on all Lua types, including primitives. For numbers, strings, booleans, and nil, its behavior is identical to the == operator because these types do not have metamethods.

print(rawequal(1, 1))          -- true
print(rawequal("hello", "hello")) -- true
print(rawequal(nil, nil))       -- true
print(rawequal(true, false))    -- false

This makes rawequal useful as a general-purpose identity check that works uniformly across all types without needing to think about whether a type has custom equality behavior.

When to Use rawequal

Reach for rawequal when:

  • You are implementing a custom __eq metamethod and need an identity check without triggering recursion
  • You are using tables as keys and need to verify that a key object is the exact same reference
  • You want to confirm whether two values are the same object, not just equal in value
  • You are building caching or interning systems where object identity matters

For value-based equality comparisons, use the == operator instead.

See Also

  • next — iterate raw table keys without triggering metamethods
  • rawget — read a table value without invoking __index
  • rawset — write a table value without invoking __newindex
  • lua-metatables — learn how __eq and other metamethods work