GMS 2 Telling if a variable is a number or a data structure

Discussion in 'Programming' started by mdbussen, Nov 17, 2018.

  1. mdbussen

    mdbussen Member

    Joined:
    Jul 8, 2016
    Posts:
    62
    ... 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???
     
  2. Dogarooski

    Dogarooski Member

    Joined:
    Jun 21, 2016
    Posts:
    66
    I think if you actually need to tell the difference, you're probably doing something wrong. You shouldn't be writing code that has to check a variable's current type unless you're making some introspective debug console or something like that. You certainly don't need something like for a save system.
     
  3. mdbussen

    mdbussen Member

    Joined:
    Jul 8, 2016
    Posts:
    62
    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.
     
  4. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,542
    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.
     
    Joe Ellis and mdbussen like this.
  5. EvanSki

    EvanSki King of Raccoons

    Joined:
    Apr 17, 2018
    Posts:
    580
    Couldn't you use?
    Code:
    real(0)
    
    ds_map(0)
    
    ds_list(0)
     
  6. chamaeleon

    chamaeleon Member

    Joined:
    Jun 21, 2016
    Posts:
    975
    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.
     
    EvanSki likes this.
  7. mdbussen

    mdbussen Member

    Joined:
    Jul 8, 2016
    Posts:
    62
    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.
     
  8. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    936
    You just summed it up, its all indices
    even buffers and vertex buffers all start at 0
    same number as the name can use them
     
    EvanSki likes this.
  9. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    936
    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,
     
  10. chamaeleon

    chamaeleon Member

    Joined:
    Jun 21, 2016
    Posts:
    975
    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 likes this.
  11. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    936
    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
     
  12. IndianaBones

    IndianaBones Member

    Joined:
    Jul 5, 2016
    Posts:
    2,204
    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.
     
  13. icuurd12b42

    icuurd12b42 TMC Founder GMC Elder

    Joined:
    Apr 22, 2016
    Posts:
    1,839
    >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.
     
    mdbussen likes this.
  14. mdbussen

    mdbussen Member

    Joined:
    Jul 8, 2016
    Posts:
    62
    lol thanks for clearing it up :D
     
  15. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    936
    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: Nov 20, 2018

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice