1. Hello Guest! It's with a heavy heart that we must announce the removal of the Legacy GMC Archive. If you wish to save anything from it, now's the time! Please see this topic for more information.
    Dismiss Notice

Discussion [Suggestion] ds list / map / grid - quick constructors

Discussion in 'GameMaker Studio 2 Community Tech Support' started by gnysek, Jul 21, 2017.

  1. gnysek

    gnysek Member

    Joined:
    Jun 20, 2016
    Posts:
    1,314
    GMS2 added a great functionality, that you can write:
    Code:
    var a = [1,2,3,4];
    instead
    Code:
    var a;
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;
    a[3] = 4;
    like it was in all previous GM versions.

    So, why not extend it further to other structures ?
    I think that ds_list, ds_map and ds_grid can be extended this way easily:

    Code:
    map = [? "a" => 1, "b" => 2, "c" => "string",5 => sprite_name];
    would be same as:
    Code:
    map = ds_map_create();
    map[? "a" ] = 1;
    map[? "b" ] = 2;
    map[? "c" ] = "string";
    map[? 5 ] = sprite_name;
    Code:
    list = [| 1, "test", 13, sprite_another];
    would be same as:
    Code:
    list = ds_list_create();
    list[| 0] = 1;
    list[| 1] = "test";
    list[| 2] = 13;
    list[| 3] = sprite_another;
    and for grid (I choose # character as line separator, you're giving it by rows not by columns):
    Code:
    grid = [# 1,2,3,4,5 # 6,7,8,9 # 10];
    would be equal to:
    Code:
    grid = ds_grid_create(5, 3);
    grid[# 0, 0] = 1;
    grid[# 1, 0] = 2;
    grid[# 2, 0] = 3;
    grid[# 3, 0] = 4;
    grid[# 4, 0] = 5 ;
    
    grid[# 0, 1] = 6;
    grid[# 1, 1] = 7;
    grid[# 2, 1] = 8;
    grid[# 3, 1] = 9 ;
    
    grid[# 0, 2] = 10;

    This should require no change in runner, as this could be replaced by pre-compile part, so compiler gets same code as without this change.

    As proof of concept I made a javascript parser which does what I described above. You can update code to see changes (however this is a simple parser, so putting arrays inside ds_xxx or ommiting ; would break it). I understand that for YYG it will took longer than 30 minutes (which I lost on it), since I've added no stacking for substructures and no code editor parsing, but still this seems not that hard to do.

    Check it here: https://jsfiddle.net/gnysek/x3c7eL4c/
     
    john5879 likes this.
  2. Mike

    Mike nobody important GMC Elder

    Joined:
    Apr 12, 2016
    Posts:
    2,413
  3. psyke

    psyke Member

    Joined:
    Jun 21, 2016
    Posts:
    223
    The ds_list is OK I guess, it looks just like a regular array, but the ds_map and ds_grid looks very nasty and confusing.
    I would never use something like that to initialize a ds_map/ds_grid, I would probably create a script with a simple FOR statement.
     
    Dogarooski likes this.
  4. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    Sure the syntax isn't the best...
    But something along those lines would be nice!
    Perhaps something like c# for maps?
    Maps:
    Code:
    map = {?
      {"A", 1}
      {"B", 2}
      {"C", 3}
    }
    
    And something like this for grids?
    Code:
    Grid = {#
    {1, 2, 3, 4},
    {2, 4, 6, 8}
    }
    
     
    john5879 likes this.
  5. gnysek

    gnysek Member

    Joined:
    Jun 20, 2016
    Posts:
    1,314
    Hey, the syntax is taken from PHP / Ruby, where all arrays are hashmaps, same as ds_map :)
     
  6. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    ugh, PHP... yuck indeed
     
    Mike and Dogarooski like this.
  7. Juju

    Juju Member

    Joined:
    Jun 20, 2016
    Posts:
    414
    This obvs has limitations but it's close-ish to what you're asking:
    Code:
    list = json_decode( "[ 3, 4, 5 ]" );
    map = json_decode( "{ 'a':4, 'b':5, 'c':6 }" );
    


    pfffthaha MIKE
     
  8. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    you might as well just fix the syntax all together.

    Code:
    var array = [1,2,3,5,[2,3,5]]; //nested arrays/lists because why do we need both?
    var grid = [
        [0,0,0,0,0],
        [0,0,0,0,0],
        [0,2,0,0,0],
    ]//looks familiar
    
    array[0] = 10
    show_debug_message(array[4][1]) //prints 3
    
    var x = 1;
    var y = 2;
    show_debug_message(grid[y][x])// prints 2
    
    map = {
        "key": 10,
        "otherkey": "somevalue"
    }
    
    also you ought to be able to nest maps and arrays/lists in a similar manner

    oh and get rid of the array[x,y] garbage. its bad.
     
    Last edited: Jul 22, 2017
  9. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    What differentiates the arrays from the lists and grids?
    You need the extra character there.
     
  10. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    no you do not. lists and arrays can have the same function. grids are literally just nested arrays and lists. YYG just need to implement a proper GC.
     
  11. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    Grids are a different structure to both lists and arrays. They have extra function you know? (Region and disk).

    GM does not do any type stuff at compile time (at least, not visible to us).
    That means it cannot infer how to parse the literals. We need an explicit way to tell them apart.
     
  12. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    right. but this is a suggestion topic. if you look at Lua it has one data type for these things. in fact maps, lists, and grids are all tables in Lua. Lua knows how to handle the data based on what data the user gives it. It is also one of the fastest scripting languages. No reason why a $100 product could not do the same (Lua is free)

    there is nothing special about region and disk. you can write a function which will do the same thing to a nested array.
     
    john5879 likes this.
  13. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    I highly doubt that...
    Plenty of reasons actually. The simple fact lua has had a lot more development...
    There is.
    Since GM does not have generics, there is kow way of knowing beforehand if a list contains other lists. Only at run time.
    You would also have to check that the nested lists are all of the right size.

    Grids are also bounded, lists are not.
     
  14. Zek

    Zek Member

    Joined:
    Jun 20, 2016
    Posts:
    74
    Just liked to point out that with lists you can already do:
    ds_list_add(list, 1, "test", 13, sprite_another);
    Which is pretty similar.
     
  15. Salvakiya

    Salvakiya Member

    Joined:
    Jul 17, 2016
    Posts:
    84
    you are missing the point. Lua is free and is capable of this. gdscript uses arrays in the manner I said and I even implemented a grid class using nested arrays. its free and has been in development less time than GM. Both of these are dynamically typed languages.

    Grids being bounded is not relevant? My gdscript implementation of a grid does exactly what GM's grids do.

    on the topic of performance here is a reference. look for LuaJIT https://attractivechaos.github.io/plb/ note that strings are interned in Lua which makes looking up string keys in a table really fast but the creation of strings will be slightly more costly and there are ways around this.

    Lua and LuaJIT are easily embedded... YYG could just ditch GML all together and use LuaJIT =P.

    If I did not want GML to improve I suppose I would have the same view and just suggest not to change anything.

    edit: YYG's biggest mistake IMO is not breaking compatibility in GMS2 and reworking GML. Now we have a buggy featureless program (but its out of beta!)
     
  16. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    Yes I have said so many before.
    But it is what it is.
     
  17. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,445
    This is actually a pretty bad example, both Lua's and JS' way of organization (implicitly converting an array to hashtable on out-of-bounds-by-more-than-one write) has it that you can quickly degrade performance (by converting a large array to a large hashtable) due to a trivial programming mistake.

    All data structures have direct C++ equivalents:
    • ds_list: std::vector<value> (reallocated implicitly)
    • ds_grid: wrapper around value[][] (reallocated explicitly)
    • ds_map: std::map<value, value> (anything can be key, even arrays)
    • ds_stack: std::stack<value>
    • ds_queue: std::queue<value>
    • ds_priority: wrapper around std::list<value> or std::vector<value> (sort-on-insert)
    • arrays: std::vector<std::vector<value>> (rows are reallocated separately; rows can be differently sized; additional logic for implicit creation of arrays on write-to-non-array)
    Sure, you can do with just arrays and hashtables, but you'll pay a price for that, and there are pretty good reasons to why multiple collection types were added to the standard library.
     
    Yal and GMWolf like this.
  18. Rusky

    Rusky Member

    Joined:
    Jun 21, 2016
    Posts:
    11
    It would still be ideal to get rid of arrays- they can be replaced with a combination of ds_list, nested ds_list, and mmmaybe an automatically resized ds_grid. Their current behavior is pretty wacky and tries to do too many things at once (for example, the precise situations in which arrays are copied vs referenced is not easy to learn).

    It would also be good, I think, to get rid of the accessor symbols. GML ought to track the types of ds_ values, rather than relying on the program to specify it at use time. So instead of this:
    Code:
    my_list = ds_list_create()
    my_list[| 0] = 1
    use(my_list[| 0])
    You would write this:
    Code:
    my_list = ds_list_create() // or my_list = [| 1], or my_list = { 1 }, or some variation on that
    my_list[0] = 1
    use(my_list[0])
    This has two benefits. One is that it vastly simplifies things like JSON, where you have good reason not to know the type of some value ahead of time, and you can just ask the language, just like is_real, is_string, is_array, etc. The other is that you can write polymorphic code- a script that, say, calculates the sum of values in an array could accept either an array or a ds_list as its argument, as both would support the same [index] operator.

    If backwards compatibility is a concern, accessor syntax wouldn't be hard to deprecate and keep around for a while. Tracking the types like that could even let it issue a warning or error when used on a value that doesn't actually hold the corresponding ds_ type.
     
  19. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    Oh no.
    Arrays a amazing! I would not like to see them go!
    They are light weight (compared to ds_*), fast and garbage collected!
    Very impoortant too, They have their own type, and are uniquely identified. (Ds_* are indexed right now)
     
  20. Rusky

    Rusky Member

    Joined:
    Jun 21, 2016
    Posts:
    11
    I mean, I explicitly suggested making ds_lists just as lightweight as arrays. Give them the nicer literal and accessor syntax, track their type, and garbage collect them. The only thing you'd miss from arrays is their wacky reference vs copy behavior, which is only useful if you've got existing code that depends on it.
     
  21. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,473
    That's true. Fair enough.
     

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