SOLVED What happens to ds_list created in a function?

Jett

Digital Artist
Hi guys, let's say I have a function that accepts a string and a separator and I want to return a ds_list of substrings based on the separator. Like a explode() in php or split() in js.
GML:
function stringExplode(str,sep) {
    var length = 0;
    var lastpos = 1;
    var words = ds_list_create();
    
    for (i=1; i<string_length(str)+1; i++) {
        length ++;
        
        if (string_char_at(str, i) == sep) {
            ds_list_add(words, string_copy(str, lastpos, length));
            length = 0;
            lastpos = i+1;
        } else if ( i == string_length(str)) {
            ds_list_add(words, string_copy(str, lastpos, length));
        }
    }
    return words;
}
You see I created a ds_list in var words = ds_list_create(); and I returned it after some loop stuff. How do I ds_list_destroy to the ds_list I created earlier when the function ends on return? Is it fine to just leave it like this? Do they just keep piling up in the memory everytime I execute this function? or do they get cleaned up automatically somehow?
Thanks in advance
 

kburkhart84

Firehammer Games
They will keep piling up in memory(though they will be freed once the program is closed). If you know a function returns a data structure, then you need to free it, so in this case you would free it yourself once you are done with it in the code that called the function and received the reference to the data structure.

FYI, this is no different than before 2.3...just that now functions have more features than the "scripts" that they replaced. But as far as cleaning up data structures returned from them, nothing has changed.
 

Jett

Digital Artist
They will keep piling up in memory(though they will be freed once the program is closed). If you know a function returns a data structure, then you need to free it, so in this case you would free it yourself once you are done with it in the code that called the function and received the reference to the data structure.

FYI, this is no different than before 2.3...just that now functions have more features than the "scripts" that they replaced. But as far as cleaning up data structures returned from them, nothing has changed.
I see, thank you very much!
 

samspade

Member
Hi guys, let's say I have a function that accepts a string and a separator and I want to return a ds_list of substrings based on the separator. Like a explode() in php or split() in js.
GML:
function stringExplode(str,sep) {
    var length = 0;
    var lastpos = 1;
    var words = ds_list_create();
   
    for (i=1; i<string_length(str)+1; i++) {
        length ++;
       
        if (string_char_at(str, i) == sep) {
            ds_list_add(words, string_copy(str, lastpos, length));
            length = 0;
            lastpos = i+1;
        } else if ( i == string_length(str)) {
            ds_list_add(words, string_copy(str, lastpos, length));
        }
    }
    return words;
}
You see I created a ds_list in var words = ds_list_create(); and I returned it after some loop stuff. How do I ds_list_destroy to the ds_list I created earlier when the function ends on return? Is it fine to just leave it like this? Do they just keep piling up in the memory everytime I execute this function? or do they get cleaned up automatically somehow?
Thanks in advance
Just as an additional comment, since in this case you are only creating one data structure, and you are returning that data structure at the end, the above code is completely fine so long as you save the returned data structure to a variable (e.g. new_list = stringExplode(str, sep); and then later destroy new_list. If you create data structures inside of a script that are not returned, those data structures would need to be destroyed inside of the script itself.

See the following for an example:

 

Nidoking

Member
Another pattern for handling data structures as return values is to pass the index of the data structure into the function as an argument. The function then simply populates the data structure and returns nothing (or a success/failure value). This ensures that there's no confusion about which scope is responsible for destroying the data structure - whoever created it is always responsible for destroying it. You do have to be careful about reusing the same data structure in some cases, but it's a question of which problem you feel more like tracking down if it happens - leaking memory/handles, or corrupted data structures in rare cases.
 

FrostyCat

Redemption Seeker
Why not just use an array that you don't have to manually clean, instead of a list that you do? Unless entries are actively being inserted or deleted from the middle, there's a clear advantage to using an array. Returning a list every time multiple-valued returns are involved is an old-hat book line that should have died out in at the turn of GMS 1.3.
 

kburkhart84

Firehammer Games
Why not just use an array that you don't have to manually clean, instead of a list that you do? Unless entries are actively being inserted or deleted from the middle, there's a clear advantage to using an array. Returning a list every time multiple-valued returns are involved is an old-hat book line that should have died out in at the turn of GMS 1.3.
This... I in fact recently added a couple things to my input system that I'm re-writing and did exactly this. Its much better than worrying about data structures being deleted etc... The catch is that you do need to know what you are working with, what is expected in that array.
 
Top