Equality (==) tests fail with scripting "Position" objects

Bugs that are actually features.
Post Reply
User avatar
Reika
Filter Inserter
Filter Inserter
Posts: 582
Joined: Tue May 19, 2015 1:56 am
Contact:

Equality (==) tests fail with scripting "Position" objects

Post by Reika »

That is to say, it feels like == is using an identity check instead of semantic equality (ie .equals()).

The double-equals operator works fine with other script objects such as LuaEntity, so I imagine that this is an oversight rather than intentional.
Image

posila
Factorio Staff
Factorio Staff
Posts: 5201
Joined: Thu Jun 11, 2015 1:35 pm
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by posila »

https://www.lua.org/pil/3.2.html
Lua compares tables, userdata, and functions by reference, that is, two such values are considered equal only if they are the very same object. For instance, after the code

Code: Select all

    a = {}; a.x = 1; a.y = 0
    b = {}; b.x = 1; b.y = 0
    c = a
you have that a==c but a~=b.
I wonder if it really behaves differently for LuaEntity (ie. get first reference from create_entity and second through find_entities), but Position is just plain Lua table.
EDIT: Tried it and it does work with LuaEntity references, interesting.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5150
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by Klonan »

posila wrote:EDIT: Tried it and it does work with LuaEntity references, interesting.
Things like LuaEntity use a custom equality check defined in the C++:

Code: Select all

bool LuaEntity::equals(const LuaObject* luaObject) const
{
  return *this->entityTarget == *static_cast<const LuaEntity*>(luaObject)->entityTarget;
}
We could also set similar functions for position by setting a metatable on the returned position LuaTable

User avatar
Reika
Filter Inserter
Filter Inserter
Posts: 582
Joined: Tue May 19, 2015 1:56 am
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by Reika »

posila wrote:https://www.lua.org/pil/3.2.html
Lua compares tables, userdata, and functions by reference, that is, two such values are considered equal only if they are the very same object. For instance, after the code

Code: Select all

    a = {}; a.x = 1; a.y = 0
    b = {}; b.x = 1; b.y = 0
    c = a
you have that a==c but a~=b.
I wonder if it really behaves differently for LuaEntity (ie. get first reference from create_entity and second through find_entities), but Position is just plain Lua table.
EDIT: Tried it and it does work with LuaEntity references, interesting.
Klonan wrote:
posila wrote:EDIT: Tried it and it does work with LuaEntity references, interesting.
Things like LuaEntity use a custom equality check defined in the C++:

Code: Select all

bool LuaEntity::equals(const LuaObject* luaObject) const
{
  return *this->entityTarget == *static_cast<const LuaEntity*>(luaObject)->entityTarget;
}
We could also set similar functions for position by setting a metatable on the returned position LuaTable
The reason that this is kind of an important thing with Position and Area/BoundingBox is that both of those objects can have multiple internal structures (x/y vs [1]/[2] and the fact that left_top/bottom_right is optional in Area), meaning a comparison is rather nontrivial and prone to issues. Combine that with the fact that Position and Area are likely to be compared for a large number of reasons, and I imagine that this can both simplify code and save a lot of headache for a great many people.
Image

Rseding91
Factorio Staff
Factorio Staff
Posts: 13204
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by Rseding91 »

Position and area will only ever be defined 1 way when you read them from the game: position with x/y and area with left_top/right_bottom.

I'm not going to implement metatable __eq for position and area because that would mean every single one of them would need another lua table + save/load/restore the meta table every time the game saves/loads.

That would add a *massive* amount of overhead to those things existing in any mod and simply isn't worth it. There's already measurable overhead to have position be a table with x/y instead of simply returning 2 integers when called.
If you want to get ahold of me I'm almost always on Discord.

Fractaliste
Inserter
Inserter
Posts: 28
Joined: Wed Dec 06, 2017 9:20 am
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by Fractaliste »

Klonan wrote:
Fri Sep 07, 2018 6:55 pm
posila wrote:EDIT: Tried it and it does work with LuaEntity references, interesting.
Things like LuaEntity use a custom equality check defined in the C++:

Code: Select all

bool LuaEntity::equals(const LuaObject* luaObject) const
{
  return *this->entityTarget == *static_cast<const LuaEntity*>(luaObject)->entityTarget;
}
We could also set similar functions for position by setting a metatable on the returned position LuaTable
I'm not familiar with C++, does it mean I can safely check if entity1 == entity2 (instead of checking both entity have same prototype name, belongs to same surface and are at same position) to ensure that entity1 is the same object ingame as entity2 ?

User avatar
darkfrei
Smart Inserter
Smart Inserter
Posts: 2903
Joined: Thu Nov 20, 2014 11:11 pm
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by darkfrei »

Maybe some is_deep_equal function?

Rseding91
Factorio Staff
Factorio Staff
Posts: 13204
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Equality (==) tests fail with scripting "Position" objects

Post by Rseding91 »

Fractaliste wrote:
Thu Jan 17, 2019 2:08 pm
I'm not familiar with C++, does it mean I can safely check if entity1 == entity2 (instead of checking both entity have same prototype name, belongs to same surface and are at same position) to ensure that entity1 is the same object ingame as entity2 ?
Yes.
If you want to get ahold of me I'm almost always on Discord.

Post Reply

Return to “Not a bug”