Return nil if key does not exist in object

Things that we aren't going to implement
Post Reply
FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Return nil if key does not exist in object

Post by FuryoftheStars »

I have a function in control.lua that can take as inputs either LuaTilePrototype or LuaEntityPrototype, but what I'm finding is that I can't tell which I've been passed within the function because .type does not exist in LuaTilePrototype and, rather than returning nil, it errors the game.

Can objects be modified such that if the key does not exist that they return nil instead of generating an error? I feel like that'd be the better approach in case there are other scenarios where this could occur that I don't know of, but I suppose in lacking that, can .type be added to LuaTilePrototype?
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

Pi-C
Smart Inserter
Smart Inserter
Posts: 1639
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Return nil if key does not exist in object

Post by Pi-C »

FuryoftheStars wrote:
Wed Jun 15, 2022 3:46 am
I have a function in control.lua that can take as inputs either LuaTilePrototype or LuaEntityPrototype, but what I'm finding is that I can't tell which I've been passed within the function because .type does not exist in LuaTilePrototype and, rather than returning nil, it errors the game.
How about querying object_name instead of type?
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

Pi-C wrote:
Wed Jun 15, 2022 6:30 am
FuryoftheStars wrote:
Wed Jun 15, 2022 3:46 am
I have a function in control.lua that can take as inputs either LuaTilePrototype or LuaEntityPrototype, but what I'm finding is that I can't tell which I've been passed within the function because .type does not exist in LuaTilePrototype and, rather than returning nil, it errors the game.
How about querying object_name instead of type?
Thanks, that could work for my purposes, though I feel it'd still be better if it simply didn't error out (if that's possible, depending on how they have their objects and error handling set up internally).
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

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

Re: Return nil if key does not exist in object

Post by Rseding91 »

In the vast majority of the usages asking for an invalid key/method is an error and silently suppressing that error by returning nil isn't doing mod developers a favor.

Ideally the game could verify that the API calls are even vaguely possible before they get executed but due to Lua being Lua that isn't possible.
If you want to get ahold of me I'm almost always on Discord.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

Rseding91 wrote:
Wed Jun 15, 2022 3:59 pm
In the vast majority of the usages asking for an invalid key/method is an error and silently suppressing that error by returning nil isn't doing mod developers a favor.

Ideally the game could verify that the API calls are even vaguely possible before they get executed but due to Lua being Lua that isn't possible.
Could .type be added to LuaTilePrototype, then (and any other prototype that may be missing it)? Just being able to reference .type on any passed Prototype is easier than having to query .object_name, if it's LuaTilePrototype, then assign "tile" to some variable, if it's not, then query .type and assign that to the variable, then always reference that variable whenever I need the type. Especially in a function where I have multiple prototypes that get passed in (meant to be worked on together, not in a loop), because then I'm having to have several of these variables (or one table of the values), one for each prototype.
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

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

Re: Return nil if key does not exist in object

Post by Rseding91 »

You're describing object_name and it already exists as mentioned: https://lua-api.factorio.com/latest/Lua ... bject_name for each thing in the API.
If you want to get ahold of me I'm almost always on Discord.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

Rseding91 wrote:
Wed Jun 15, 2022 5:24 pm
You're describing object_name and it already exists as mentioned: https://lua-api.factorio.com/latest/Lua ... bject_name for each thing in the API.
Yes, but this returns the actual object name, like "LuaTilePrototype", etc, right? So in the case of LuaEntityPrototype, I'd still need to query the .type property to know exactly which entity type has been passed, correct? So in a function where it's meant to be passed either LuaTilePrototype or LuaEntityPrototype, I have to first check .object_name and see what it is before I can then query .type.
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

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

Re: Return nil if key does not exist in object

Post by Rseding91 »

FuryoftheStars wrote:
Wed Jun 15, 2022 5:36 pm
Yes, but this returns the actual object name, like "LuaTilePrototype", etc, right? So in the case of LuaEntityPrototype, I'd still need to query the .type property to know exactly which entity type has been passed, correct? So in a function where it's meant to be passed either LuaTilePrototype or LuaEntityPrototype, I have to first check .object_name and see what it is before I can then query .type.
Yes. But I question; why do you not simply have 2 functions: one that is meant to accept a LuaEntityPrototype and one that is meant to accept a LuaTilePrototype.

So far, the only time i've seen a legitimate use-case for a 'generic accept anything' function was a debugger someone was writing. As a mod; you should always know what you're passing around to know what you can call on it. If you've lost that information then it seems like something has gone weird in your code.
If you want to get ahold of me I'm almost always on Discord.

curiosity
Filter Inserter
Filter Inserter
Posts: 315
Joined: Wed Sep 11, 2019 4:13 pm
Contact:

Re: Return nil if key does not exist in object

Post by curiosity »

Why do you want such a function in the first place when tile and entity prototypes, as you have noted, don't have in common what you care about?

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

Rseding91 wrote:
Wed Jun 15, 2022 6:30 pm
But I question; why do you not simply have 2 functions: one that is meant to accept a LuaEntityPrototype and one that is meant to accept a LuaTilePrototype.
curiosity wrote:
Wed Jun 15, 2022 6:33 pm
Why do you want such a function in the first place when tile and entity prototypes, as you have noted, don't have in common what you care about?
Because I'm passing 2 prototypes at the same time, checking the collision masks of them prior to placement. Maybe they're both entities, maybe they're both tiles, maybe they're one of each. Both have the .collision_mask and .collision_mask_with_flags properties, however, the collision behavior is different if one has the "colliding-with-tiles-only" flag, so I need to know if either are a tile and, so far, I don't see a (good) way of checking these built in. I mean, LuaTile has a .collides_with and LuaSurface has entity_prototype_collides, but both of these require at least one of the two prototypes I'm trying to compare to already be placed into the world, which means that if by doing so I'm having to remove other entities/tiles first, I then need to also track what I just removed so I can place it back in case what I was trying to do doesn't work (because what I'm doing is dynamic and can be influenced by the terrain and what the player may or may not have already done before even loading my mod, or what other mods are in use that may be altering things).

If you want, I suppose this request would make this particular use case moot. I just didn't want to assume that my use case is the only possible use case. (Edit: And the idea of asking for a dedicated function for that didn't occur to me until an hour later. :P)

Edit2: Forgot to throw in here, the entity offshore-pump has a secondary collision mask as well, so I need to be able to tell when one of those is passed in, hence why .type on everything would just be easier vs .object_name.
Last edited by FuryoftheStars on Wed Jun 15, 2022 8:38 pm, edited 1 time in total.
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

Pi-C
Smart Inserter
Smart Inserter
Posts: 1639
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: Return nil if key does not exist in object

Post by Pi-C »

curiosity wrote:
Wed Jun 15, 2022 6:33 pm
Why do you want such a function in the first place when tile and entity prototypes, as you have noted, don't have in common what you care about?
It may also make sense if you have no direct control about what arguments are passed on to your function: think of remote calls from other mods that pass on unexpected values. Also, as already mentioned by Rseding91, it's quite useful for debugging. For example, while working on a mod I like to see exactly what function gets called with what arguments, and it really doesn't help if for every object I try to look at I get just __self = "userdata". Using object_name, I know what properties I'm allowed to query and can log something more reasonable, like this:

Code: Select all

====================================================================================================
Entered event script for on_gui_checked_state_changed
Event data: tick = 291182, player_index = 1, element = LuaGuiElement checkbox "GCKI_select_area_vehicle_list_toggle_lock_776"
(@__GCKI__/scripts/gui.lua: 423)
====================================================================================================
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!

quyxkh
Smart Inserter
Smart Inserter
Posts: 1027
Joined: Sun May 08, 2016 9:01 am
Contact:

Re: Return nil if key does not exist in object

Post by quyxkh »

You can easily do this yourself, run the prototypes you care about and build a plain lua table keying off the name. `type` in the entity prototypes is an attribute value the created entity will have, it's not anything to do with the prototype itself.

Code: Select all

mystuff={} empty={}
for k,v in pairs(game.get_filtered_entity_prototypes{}) do mystuff[k]={whatever} end 
for k,v in pairs(game.get_filtered_tile_prototypes{}) do mystuff[k]={whatever}  end
and now `(mystuff[arg.name] or empty).type` will be nil if you didn't set it.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

quyxkh wrote:
Wed Jun 15, 2022 7:49 pm
You can easily do this yourself, run the prototypes you care about and build a plain lua table keying off the name. `type` in the entity prototypes is an attribute value the created entity will have, it's not anything to do with the prototype itself.

Code: Select all

mystuff={} empty={}
for k,v in pairs(game.get_filtered_entity_prototypes{}) do mystuff[k]={whatever} end 
for k,v in pairs(game.get_filtered_tile_prototypes{}) do mystuff[k]={whatever}  end
and now `(mystuff[arg.name] or empty).type` will be nil if you didn't set it.
I know what .type is. It's what will tell me if the entity is a tree, or a turret, or any of the other things. The fact that LuaTilePrototype is missing this so that I can't just query .type on any given passed prototype is the issue, though.

And frankly, I'm getting tired of being told "you can do this yourself by just manually building a table blah blah blah" as if that's the solution (vs getting the request pushed through). There already exists a table of everything in the game right in the LuaGame object. Why should I add extra processing overhead and save file bloat for something that already exists but just needs 1 property added to it that shouldn't hurt the vanilla game in any way? I mean, what if "everything (I) care about" in the game is everything? And I may not be the only one that needs something like this, so why suggest this as a "solution" for each modder? After 50-100 mods all doing the same thing, that's going to add a decent amount of extra time and save file bloat.
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

curiosity
Filter Inserter
Filter Inserter
Posts: 315
Joined: Wed Sep 11, 2019 4:13 pm
Contact:

Re: Return nil if key does not exist in object

Post by curiosity »

FuryoftheStars wrote:
Wed Jun 15, 2022 8:36 pm
And frankly, I'm getting tired of being told "you can do this yourself by just manually building a table blah blah blah" as if that's the solution (vs getting the request pushed through). There already exists a table of everything in the game right in the LuaGame object. Why should I add extra processing overhead and save file bloat for something that already exists but just needs 1 property added to it that shouldn't hurt the vanilla game in any way? I mean, what if "everything (I) care about" in the game is everything? And I may not be the only one that needs something like this, so why suggest this as a "solution" for each modder? After 50-100 mods all doing the same thing, that's going to add a decent amount of extra time and save file bloat.
Why, you ask? Because you can't always have everything handed to you. Because the world isn't perfect. Why should the devs solve your problems? Why should they add bloat to their code? You have to work with what you can get. So stop complaining about the injustice of the world and do something productive.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

curiosity wrote:
Wed Jun 15, 2022 10:54 pm
FuryoftheStars wrote:
Wed Jun 15, 2022 8:36 pm
And frankly, I'm getting tired of being told "you can do this yourself by just manually building a table blah blah blah" as if that's the solution (vs getting the request pushed through). There already exists a table of everything in the game right in the LuaGame object. Why should I add extra processing overhead and save file bloat for something that already exists but just needs 1 property added to it that shouldn't hurt the vanilla game in any way? I mean, what if "everything (I) care about" in the game is everything? And I may not be the only one that needs something like this, so why suggest this as a "solution" for each modder? After 50-100 mods all doing the same thing, that's going to add a decent amount of extra time and save file bloat.
Why, you ask? Because you can't always have everything handed to you. Because the world isn't perfect. Why should the devs solve your problems? Why should they add bloat to their code?
It's not a matter of having "everything handed to (me)". I know how to solve this myself and already have. It's a matter of reducing code complexity where it's not needed (because the game already has ready access to all of this information while processing everything from the data stage) and not needing to "reinvent the wheel" in a language that runs slower than the native game's. And it's 1 string property on the object vs a whole table (as in the suggestion I was replying to) per mod that needs it. The "bloat" isn't comparable.
curiosity wrote:
Wed Jun 15, 2022 10:54 pm
So stop complaining about the injustice of the world and do something productive.
:lol:
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

robot256
Filter Inserter
Filter Inserter
Posts: 594
Joined: Sun Mar 17, 2019 1:52 am
Contact:

Re: Return nil if key does not exist in object

Post by robot256 »

Returning nil for an invalid parameter is bad because of the reasons given by the devs-- type-property errors are invaluable in debugging the vast majority of mods.

Besides, nil is a valid return value for some properties, so while returning nil for invalid properties might work for Fury's polymorphic case, it wouldn't help in a generic application that wants to know that the property exists and is nil. There really isn't any reason to complain about making a nested IF statement to retrieve a fixed list of parameters from a fixed number of types.

What would actually improve things is moving the "valid property" list into the API as a separate accessible table. There is value in having this update without each debug mod author having to change their copy of the table. But of course, anyone should be able to automate the generation of the master table if the machine-readable API documentation works as advertised.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

robot256 wrote:
Thu Jun 16, 2022 1:27 am
Returning nil for an invalid parameter is bad because of the reasons given by the devs-- type-property errors are invaluable in debugging the vast majority of mods.

Besides, nil is a valid return value for some properties, so while returning nil for invalid properties might work for Fury's polymorphic case, it wouldn't help in a generic application that wants to know that the property exists and is nil. There really isn't any reason to complain about making a nested IF statement to retrieve a fixed list of parameters from a fixed number of types.
FuryoftheStars wrote:
Wed Jun 15, 2022 4:35 pm
Rseding91 wrote:
Wed Jun 15, 2022 3:59 pm
In the vast majority of the usages asking for an invalid key/method is an error and silently suppressing that error by returning nil isn't doing mod developers a favor.

Ideally the game could verify that the API calls are even vaguely possible before they get executed but due to Lua being Lua that isn't possible.
Could .type be added to LuaTilePrototype, then (and any other prototype that may be missing it)? [...]
And just for clarity sake, I'm not saying add .type with a nil value in this case.
Edit: Should probably throw this in there, too:
FuryoftheStars wrote:
Wed Jun 15, 2022 7:20 pm
If you want, I suppose this request would make this particular use case moot. I just didn't want to assume that my use case is the only possible use case.
End edit.
robot256 wrote:
Thu Jun 16, 2022 1:27 am
What would actually improve things is moving the "valid property" list into the API as a separate accessible table. There is value in having this update without each debug mod author having to change their copy of the table. But of course, anyone should be able to automate the generation of the master table if the machine-readable API documentation works as advertised.
For my use here (the reason for the request), I'm not sure if it'd be much more useful than just checking .object_name, but if you think it may have value with other things, then I'd be all for that.
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

quyxkh
Smart Inserter
Smart Inserter
Posts: 1027
Joined: Sun May 08, 2016 9:01 am
Contact:

Re: Return nil if key does not exist in object

Post by quyxkh »

FuryoftheStars wrote:
Wed Jun 15, 2022 8:36 pm
[snip]"you can do this yourself by just manually building a table blah blah blah" as if that's the solution (vs getting the request pushed through).
That is the solution. It's like five lines of code you run in control.lua, once when the game starts up. Takes much less than 10ms (two, on my getting-ancient rig) to run those tables. Milliseconds. Once per play session while you're getting settled. That's the horrifying effort and cost you're so volubly and endlessly demanding somebody else relieve you and your legion of suffering users of.
There already exists a table of everything in the game right in the LuaGame object.
No, there doesn't. There are ten tables, of ten different kinds of things in the game. Two of them are similar enough for your purposes you wanted to treat them as identical. They're not.
Why should I add extra processing overhead and save file bloat for something that already exists but just needs 1 property added to it that shouldn't hurt the vanilla game in any way?
Because (a) that "save file bloat" is as imaginary as your imagined horde of other modders wanting to treat tiles and entities as identical, sometimes, maybe, and (b) because that's how you build the mod you want to build.

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

Re: Return nil if key does not exist in object

Post by Rseding91 »

A small addon to the conversation: if a given method/property is valid for something like an entity/player can runtime depend on the state of the entity so saying 'this method/property is valid for this object' is not a simple docs-parsing task.

Example: reading data about a crafting queue from a player; if the player is not a controller type that has one then it is invalid to read/write the crafting queue. This is only known at runtime.
If you want to get ahold of me I'm almost always on Discord.

FuryoftheStars
Smart Inserter
Smart Inserter
Posts: 2483
Joined: Tue Apr 25, 2017 2:01 pm
Contact:

Re: Return nil if key does not exist in object

Post by FuryoftheStars »

quyxkh wrote:
Thu Jun 16, 2022 6:15 am
you're so volubly and endlessly demanding
I’m not demanding jack. I’m defending my (revised) request against people saying my request is not needed because I can hack together my own solution. Seriously, how many things have the devs added to this game over the years that weren’t needed because the modder could do it themselves, but by the devs adding it things were made simpler? It’s 2 lines 1 line of code in the base game (per object that is currently missing it: 1 to define it in the object definition (with a static value), and 1 to actually set a value while they’re compiling the data.raw objects into them) that won’t hurt anything by including.

Look, you want to always have to build your own solutions for things? Feel free to not use many of the APIs and properties available to us that made modding easier for this game.

It doesn’t matter to me if it’s only a 5 ms savings. It’s still a savings that most likely doesn’t even have a measurable impact on the base game, let alone any impact felt would only be at the end of the data stage while they’re compiling them into their final objects. And I’m sorry, but I do not think in the mindset “it’ll only be me that needs this.”

If the devs ultimately decide they don’t want to do it, fine, but the arguments I’m seeing so far on why they shouldn’t don’t hold any water.

Edit: Updated “2 lines” of code to “1 line” and altered the rest to reflect that. /Edit

—————————————
Rseding91 wrote:
Thu Jun 16, 2022 12:52 pm
A small addon to the conversation
Yeah, I think I get this. I’m revising my ask to being: can you include the .type property on LuaTilePrototype (and any other prototype, really, where type could be valid on) with a valid return value?

I realize that means for (example) all LuaTilePrototype objects the value would just then be “tile”, but I do believe it would be easier just being able to query .type on all prototypes in generic functions. This avoids having to do any of the following:
a) Have additional logic to first query .object_name and sort out what object it is, then if it’s a LuaEntityPrototype query .type anyway, but also ultimately having to store this result in a separate variable for future reference for the life of the function.
b) Run extra code on every game load to (re)populate a table of name/type pairs, which will require doing the first part of (a), that then you reference with the object’s .name property to get the paired type.
c) Spilt some of your code out into separate specialized functions, essentially duplicating some of the code, but will still require doing the first part of (a) so you can sort them out to the correct functions.

Again, I just want to make it clear: I’m no longer asking for the return of nil if the property does not exist (or run-time compilation that checks for if the property is valid on the given object). I’m merely asking for .type to be included and populated on all prototype objects instead of just LuaEntityPrototype.

Edit2: Also, want to point out, while I still believe it’d be a “nice have”, if the other suggestion thread I linked to in an earlier post were to be implemented, then my use case for this would be removed.
My Mods: Classic Factorio Basic Oil Processing | Sulfur Production from Oils | Wood to Oil Processing | Infinite Resources - Normal Yield | Tree Saplings (Redux) | Alien Biomes Tweaked | Restrictions on Artificial Tiles

Post Reply

Return to “Won't implement”