• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

HIVE

HappyTauren
HappyTauren
You have to destroy local objects such as groups (how would automatic cleanup even work? would local units also get destroyed randomly? etc.), but you don't have to null any handles, ever. You also don't have to use workarounds when handles are returned, because if a function returns a handle, wurst will assign the value of the handle to a global, null the local, and return the global.

Wurst manual doesn't talk about leaks cause the only leaks you should care about are those that are caused by your programming, and not by jass' faulty design.

You have to destroy LinkedLists too, and HashMaps, etc. They are all objects added to their stacks.
Chaosy
Chaosy
I'd imagine that the local variable is simply nulled at the end of the block it is declared. Which is not perfect, but probably pretty good all things considered.

So I do not have to null local units then? I am pretty sure that is standard practice in JASS so it is either that or wurst somehow sorts that out in the background.
HappyTauren
HappyTauren
Wurst uses local optimizations. This means that local variables keep being reused. Nulling them at the end of the block is meaningless, since they're going to be reset and re-purposed anyways.

Wurst has really good control over locals. As I said, it not only reuses them (when they are not in the same scope), it also nulls all handles at the end of the function. This being a "standard JASS" practice has nothing to do with the user, since wurst takes care of it.

You can generate the code and see for yourself, just don't turn on optimization (else you won't be able to read anything), but you can turn on local optimizations to see what wurst does with locals.
Chaosy
Chaosy
Interesting. So only groups, locations and similar then, great!
HappyTauren
HappyTauren
You don't have to null them, but yes, you have to destroy them. You don't have to "null" tuples of any sort, either, since they are just globals in disguise.
Chaosy
Chaosy
Yeah I gotcha. I avoid hashmap and linked lists if I can so I imagine I will have some leaks eventually, but if those are the only leaks it wont impact performance. At least not enough for the player to notice.

I use Table a fair lot though, will need to take a look there as I think I might have forgotten to flush that.
HappyTauren
HappyTauren
Why are you avoiding lists and hashmaps?

And it isn't about the performance, if hashmaps and lists are leaking, they'll eventually reach the 8191 instance limit, so the map will become unplayable. It's just as it has always been with allocation in jass.

Structural object leaks are a serious issue in most programming languages, and wurst is no different.
Chaosy
Chaosy
It will have to be a really gigantic map for that to be an issue. I'll keep it in mind regardless though.

Hashmaps are limited. Mainly because you can only bind one of every type per key. For example if I want to save 2 reals, I cannot do that.

As for linked lists.. I do not really have anything against them, I just f eel like I do not need it very often. I'd much rather use a unit group instead of a linked list of units for example.
HappyTauren
HappyTauren
??? What do you mean one type per key? That's exactly the point of it xD

The point is to use the map to represent the relationship between two objects, not to dump as much data into it and later be unable to debug it correctly. I have never once had an issue of map not being sufficient or good for my use in wurst, so what's your use case where it's not suited for?

Well, if you don't run into issues with unit groups, that's fine then. However, linked lists are used for a ton of other things instead of arrays, because arrays make the code painful to watch and debug.

BTW, I added a GroupUtils library, so you can use getGroup() and .release() now.
HappyTauren
HappyTauren
BTW, I've been planning to compile a "proper wurst practices" article for a while but I don't really have the time since I am doing a ton of other things. Explaining why and when to use HashMaps and LinkedLists will be an important part of it.
Chaosy
Chaosy
Err, obviously not. I do not have any issues with a normal hashtable, it is my goto choice of data structure. I just find the hashmap extension to be limited. Yes, it is good when you only need to save one value per type, but that is not very often for me so far.

Yeah I saw that library, not tested it yet though. Does it add functionality other than better constructors / deconstructors?

I had this suggestion to a while back where I wanted to be able to do something like group.kill() which would kill all units in that group. That would probably never be used but there are other unit methods I could very well see myself using sometime.

Perhaps not super-mega useful all the time but I think it would be a pleasant addition.
HappyTauren
HappyTauren
I meant HashMap, I fixed my post.

Anyways, adding group.doAnythingWithUnits() would be bad for more reasons than I can count. First, it is not the group's job to do anything with units. In object oriented programming, whatever is the subject, is what DOES or RETURNS things. Saying "group.kill" means "yo group, kill units in yourself!", and group should be just a container. It shouldn't be an actor that does things. Second, it's pointless to write extension functions for anything that you can easily iterate over, and if you added every little function you thought "might come handy" you'd soon end up with 1000 of them, for no reason.
HappyTauren
HappyTauren
And all that to save a line of code, when you could do

for u in/from group
u.kill()

which will make sense to everyone reading your code, instead of an obscure extension function. It also makes sense in the light of object oriented programming, where group should be treated as a container, you aren't saying "group, kill units inside yourself!", instead, you're saying "iterator, pick all units in the group, and I will decide what I want to do with them", and when you say "u.kill" this means "I order this unit to die" or "unit, kill yourself!"
Chaosy
Chaosy
I recently had a class about readability which is why I am still tainted by putting readability over everything else for that class ;P

While I wont argue about the philosophy about how wurst should be structured and treated, I do not think having a lot of methods is bad. I'd rather have too many than too few. Since it is all optional with importing the packages you want anyway.

Not that it matters, I am not really pushing for it, it is just a minor thing I would like to have personally. It is not a big loss on my end, just convenience.
Top