GameMaker Telling if a variable is a number or a data structure

M

mdbussen

Guest
... Is there really no way to tell if a given variable is an integer value or a data structure? This seems insane to me. I ran into this issue when I was working on a save system for my game and it is bizarre. Given the following code:

Code:
var this_map = ds_map_create();
show_debug_message("this_map is a " + typeof(this_map));
ds_map_destroy(this_map);
  
var this_list = ds_list_create();
show_debug_message("this_list is a " + typeof(this_list));
ds_list_destroy(this_list);
  
var this_grid = ds_grid_create(2,2);
show_debug_message("this_grid is a " + typeof(this_grid));
ds_grid_destroy(this_grid);
  
var this_queue = ds_queue_create();
show_debug_message("this_queue is a " + typeof(this_queue));
ds_queue_destroy(this_queue);
  
var this_stack = ds_stack_create();
show_debug_message("this_stack is a " + typeof(this_stack));
ds_stack_destroy(this_stack);
  
var this_priority = ds_priority_create();
show_debug_message("this_priority is a " + typeof(this_priority));
ds_priority_destroy(this_priority);
  
var this_int = 1;
show_debug_message("is this_int a ds_map? " + (ds_exists(this_int, ds_type_map) ? "yes!" : "no"));
  
var this_int = 1;
show_debug_message("is this_int a ds_priority? " + (ds_exists(this_int, ds_type_priority) ? "yes!" : "no"));
The output to the console is:

Code:
this_map is a number
this_list is a number
this_grid is a number
this_queue is a number
this_stack is a number
this_priority is a number
is this_int a ds_map? yes!
is this_int a ds_priority? no
(Note that the last two checks are different just because I happen to be using ds_map but not ds_priority in my project).

Is there any way to tell the difference between an integer value and a data structure???
 
M

mdbussen

Guest
Let's ignore what I'm using it for and just address the fundamental question of whether or not it is possible.

It seems supremely odd to me that GMS2 has "typeof" and "ds_exists" to tell you the types of variables and data structures, but then cannot tell the difference between data structures and integers.
 

FrostyCat

Redemption Seeker
It's impossible in current versions of GM without storing the type separately.

Data structures in GML are tracked using numeric IDs. When you create a data structure, you are not storing the data structure itself but a number identifying that data structure for later use. This is a legacy from pre-Studio versions of GM, which supported only real and string types. As a result, a real value 0, a map with ID 0, a list with ID 0, etc. can all coexist at the same time, and there would be no strictly local way to tell them apart.

Promoting data structures to a true data type is on the Roadmap, but it has been there for years and you shouldn't expect immediate action.
 

Evanski

Raccoon Lord
Forum Staff
Moderator
As a result, a real value 0, a map with ID 0, a list with ID 0, etc. can all coexist at the same time, and there would be no strictly local way to tell them apart.
Couldn't you use?
Code:
real(0)

ds_map(0)

ds_list(0)
 

chamaeleon

Member
Couldn't you use?
Code:
real(0)

ds_map(0)

ds_list(0)
What do you think these things would do (if you had actually used proper functions.. maybe you meant is_real(), ds_map_exists(), etc.), rather than what you would wish happened? The meaning of the value comes from which function you call. If you call a ds_map function, the number will be used internally in that function as a ds_map reference, if you call a ds_list function, it will attempt to use it as a ds_list reference. In any case, the only thing that matters as far as the function called is concerned, is whether the number corresponds to a reference of an allocated data structure type the function works on. It does not care if you have a bug that makes you pass in a value from the "wrong" variable by mistake. If its value happens to correspond to an ID that has been created the function will happily perform whatever it is supposed to on that data structure.
 
Last edited by a moderator:
M

mdbussen

Guest
god it's even worse than I thought. "ds_exists" doesn't even identify data structure type accurately, it just returns true if the specified data structure with that integer reference exists at all. So

Code:
var my_map = ds_map_create();
var my_list = ds_list_create();
var my_queue = ds_queue_create();
var my_grid = ds_grid_create(2,2);

show_debug_message(string(my_map) + " " + string(my_list) + " " + string(my_queue) + " " + string(my_grid));

show_debug_message(string(ds_exists(my_map, ds_type_map)) + " " + string(ds_exists(my_map, ds_type_list)) + " " + string(ds_exists(my_map, ds_type_queue)) + " " + string(ds_exists(my_map, ds_type_grid)));
show_debug_message(string(ds_exists(my_list, ds_type_map)) + " " + string(ds_exists(my_list, ds_type_list)) + " " + string(ds_exists(my_list, ds_type_queue)) + " " + string(ds_exists(my_list, ds_type_grid)));
show_debug_message(string(ds_exists(my_queue, ds_type_map)) + " " + string(ds_exists(my_queue, ds_type_list)) + " " + string(ds_exists(my_queue, ds_type_queue)) + " " + string(ds_exists(my_queue, ds_type_grid)));
show_debug_message(string(ds_exists(my_grid, ds_type_map)) + " " + string(ds_exists(my_grid, ds_type_list)) + " " + string(ds_exists(my_grid, ds_type_queue)) + " " + string(ds_exists(my_grid, ds_type_grid)));
returns (at least for my current project):

Code:
2 3 0 0
1 1 0 0
1 1 0 0
1 1 1 1
1 1 1 1
Note the 'my_grid' and 'my_queue' variables say that they exist as all four different "ds_types" which is incredibly misleading. I can see now why it is happening but this is completely counter-intuitive.

I guess I will have to find some way to work around this.
 

Joe Ellis

Member
What do you think these things would do (if you had actually used proper functions.. maybe you meant is_real(), ds_map_exists(), etc.), rather than what you would wish happened? The meaning of the value comes from which function you call. If you call a ds_map function, the number will be used internally in that function as a ds_map reference, if you call a ds_list function, it will attempt to use it as a ds_list reference. In any case, the only thing that matters as far as the function called is concerned, is whether the number corresponds to a reference of an allocated data structure type the function works on. It does not care if you have a bug that makes you pass in a value from the "wrong" variable by mistake. If its value happens to correspond to an ID that has been created the function will happily perform whatever it is supposed to on that data structure.
It seems like your understanding is warped, its as simple as numbers from 0 to however many of that type of thing there are, you can do it using 0, 1, etc.
cus all the functions' argument of the ds, buffer, pretty much anything is just an index, from 0 upwards, so the first buffer in the game is 0, then 1. you get the picture,
but it never goes backwards, thats why buffer_exists works, cus that index has bin and gone,
 

chamaeleon

Member
It seems like your understanding is warped, its as simple as numbers from 0 to however many of that type of thing there are, you can do it using 0, 1, etc.
cus all the functions' argument of the ds, buffer, pretty much anything is just an index, from 0 upwards, so the first buffer in the game is 0, then 1. you get the picture,
but it never goes backwards, thats why buffer_exists works, cus that index has bin and gone,
You may not realize it, but I said exactly the same thing, although I didn't use the explicit values 0, 1, and so on. I fail to see what part of my explanation is warped.
 

Joe Ellis

Member
You may not realize it, but I said exactly the same thing, although I didn't use the explicit values 0, 1, and so on. I fail to see what part of my explanation is warped.
Ok I kind of wondered whether you'd say that, cus from just the stuff you wrote you couldn't tell whether you knew what you were on about or not
so you've validated it :D

You should use explicit values though here, cus then it can't be questioned
 
but it never goes backwards, thats why buffer_exists works, cus that index has bin and gone,
I don't know about buffers, but data structure index numbers now get re-used once they have been destroyed. At least, last time I tested(late last year I think) in GMS 2.
 
I

icuurd12b42

Guest
>Is there any way to tell the difference between an integer value and a data structure???

No.

is there a way to tell if an entry in a ds_list/map is another ds list or map? A sub structure?

No.

is ds_exists effing useless?

Yes.
 
M

mdbussen

Guest
>Is there any way to tell the difference between an integer value and a data structure???

No.

is there a way to tell if an entry in a ds_list/map is another ds list or map? A sub structure?

No.

is ds_exists effing useless?

Yes.
lol thanks for clearing it up :D
 

Joe Ellis

Member
I don't know about buffers, but data structure index numbers now get re-used once they have been destroyed. At least, last time I tested(late last year I think) in GMS 2.
Yeah sorry I think they changed everything recently to do that, I noticed they changed it recently with vertex buffers so I should've put 2&2 together.
It makes it simpler if you delete a ds and instantly rebuild a new version of it, cus the new ds has the same index as the one you just deleted and nothing using it has to get updated with the new index,
but if you don't remake it straight away it adds alot more work updating everything that used the old one to the new index,
But when deleting anything that has an index like this with several other things using it, it's best to keep track of the things that are being deleted and what uses them, then update everything at the end of the deletion process.
 
Last edited:
Top