• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Testing for struct equality

Status
Not open for further replies.
Level 15
Joined
Aug 7, 2013
Messages
1,337
Hi,

How does one compare two structs? My understanding is that structs are treated like objects and so they have reference semantics rather than value. That would mean that myStruct A == myStruct B is true iff they point to the exact same object/data structure in memory?

Or should we go about defining our own equals method in the struct, e.g.
method equals takes myStruct B returns boolean?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
lol, you appear to not be quite sure what structs are in vJASS.

Let me point you to a simple little thing.

http://www.hiveworkshop.com/forums/...ls-280/coding-efficient-vjass-structs-187477/

Read through that and you should then understand exactly what you need to do :p.

The == operator is allowed. You can use integer(structName) to make it just use the regular math == operator.

Operators are like

method operator hi takes nothing returns integer

edit
a struct is just an integer that refers to some position in an array. From here, it reads from a set of arrays, which are your fields.

if you want to test for equality, you can compare the integers or you can compare the arrays that the fields refer too ;). For nicer syntax, you can overload ==.

so you can do

integer(structinstance) == integer(structinstance)

or

structinstance== structinstance
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
lol, you appear to not be quite sure what structs are in vJASS.

Let me point you to a simple little thing.

http://www.hiveworkshop.com/forums/...ls-280/coding-efficient-vjass-structs-187477/

Read through that and you should then understand exactly what you need to do :p.

The == operator is allowed. You can use integer(structName) to make it just use the regular math == operator.

Operators are like

method operator hi takes nothing returns integer

edit
a struct is just an integer that refers to some position in an array. From here, it reads from a set of arrays, which are your fields.

if you want to test for equality, you can compare the integers or you can compare the arrays that the fields refer too ;). For nicer syntax, you can overload ==.

so you can do

integer(structinstance) == integer(structinstance)

or

structinstance== structinstance

When doing object equality in a language like Java, we usually write a specific equals method for that object, which does look at the fields to determine equality.

In my case though the only time I needed to compare equality among my structs is when they do point to the same data structure(s) in memory, so I don't really need to make an equals method.

Here is my example:
JASS:
struct myStruct A
endstruct
...
globals
myStruct array S
myStruct array Z
endglobals
...
function foo takes nothing returns boolean
  myStruct m = myStruct.create()
  set S[0] = m
  set Z[0] = m
  return S[0] == Z[0] //will this return true or false
endfunction
 

LeP

LeP

Level 13
Joined
Feb 13, 2008
Messages
540
When doing object equality in a language like Java, we usually write a specific equals method for that object, which does look at the fields to determine equality.

In my case though the only time I needed to compare equality among my structs is when they do point to the same data structure(s) in memory, so I don't really need to make an equals method.

Here is my example:
JASS:
struct myStruct A
endstruct
...
globals
myStruct array S
myStruct array Z
endglobals
...
function foo takes nothing returns boolean
  myStruct m = myStruct.create()
  set S[0] = m
  set Z[0] = m
  return S[0] == Z[0] //will this return true or false
endfunction

Why don't you just test it yourself?
Spoiler: yes the comparison is true.

That will throw a syntax error because it's looking for overloaded ==

integer(S[0]) == integer(Z[0])

You wot mate. The integer syntax is made to make "pointer" test if you have overloaded the ==-operator. Without overloading it defaults to "pointer"-equivalence.
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
When doing object equality in a language like Java, we usually write a specific equals method for that object, which does look at the fields to determine equality.

This is not entirely true. In both Java and Jass you have two fundamentally different types of object equality.
1. Comparing the identity with ==
2. Comparing the content with .equals(o)

Both works the exact same way in Java and Jass, except that in Java the equals method is member of Java.lang.Object and all classes inherit it.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
This is not entirely true. In both Java and Jass you have two fundamentally different types of object equality.
1. Comparing the identity with ==
2. Comparing the content with .equals(o)

Both works the exact same way in Java and Jass, except that in Java the equals method is member of Java.lang.Object and all classes inherit it.

That is what I originally intended to ask. I am aware of how == works in Java with regards to objects, and I wanted to know if the same held true of structs in JASS, since the manual (Jeff Pang) said they worked by reference semantics.

This is my understanding from the answers given, please correct me if I am wrong.

I haven't be able to test this myself as I haven't yet learned how to execute a function or write a trigger with JASS yet, otherwise I would have.

JASS:
myStruct m = myStruct.create()
set s[0] = m
set z[0] = m
s[0] == z[0] //should return true
...
s[0].destroy() //what is the value of z[0] now?  is it 0 or null?
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
JASS:
myStruct m = myStruct.create()
set s[0] = m
set z[0] = m
s[0] == z[0] //should return true

correct.

JASS:
myStruct m = myStruct.create()
set s[0] = m
set z[0] = m
s[0].destroy() //what is the value of z[0] now?  is it 0 or null?
Neither, the variables still contain the id of the object. The object even still works (the members still have their values etc.). Destroying a struct object doesnt really destroy anything, it just means that the structs id is marked as "unused" and when you create more objects of that struct the id might be used again.

This leads to some interesting effects, for example:

JASS:
struct MyStruct
    integer a
endstruct

...
local MyStruct s = MyStruct.create()
set s.a = 42
s.destroy()
s = MyStruct.create()
s.a == 42 // returns true
This happens because the "old" object is recycled and the same id is used for the new struct. Neither destroying nor creating resets any member variables.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
JASS:
myStruct m = myStruct.create()
set s[0] = m
set z[0] = m
s[0] == z[0] //should return true

correct.

JASS:
myStruct m = myStruct.create()
set s[0] = m
set z[0] = m
s[0].destroy() //what is the value of z[0] now?  is it 0 or null?
Neither, the variables still contain the id of the object. The object even still works (the members still have their values etc.). Destroying a struct object doesnt really destroy anything, it just means that the structs id is marked as "unused" and when you create more objects of that struct the id might be used again.

This leads to some interesting effects, for example:

JASS:
struct MyStruct
    integer a
endstruct

...
local MyStruct s = MyStruct.create()
set s.a = 42
s.destroy()
s = MyStruct.create()
s.a == 42 // returns true
This happens because the "old" object is recycled and the same id is used for the new struct. Neither destroying nor creating resets any member variables.

In the case above, once I do s[0].destroy() , will the value of z[0] change when the id is recycled for a "new" struct? s[0] will be equal to 0 once I call s[0].destroy() correct?
 
In the case above, once I do s[0].destroy() , will the value of z[0] change when the id is recycled for a "new" struct?

Yes, because it's just a pointer, implemented as an integer, and it's not that smart. Don't destroy structs you still intend to point to and you won't have to worry about such details.

s[0] will be equal to 0 once I call s[0].destroy() correct?

no, s[0] will still point to the integer value which previously pointed to m before you destroyed it.
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Yes, because it's just a pointer, implemented as an integer, and it's not that smart. Don't destroy structs you still intend to point to and you won't have to worry about such details.



no, s[0] will still point to the integer value which previously pointed to m before you destroyed it.

Ah so to remove a struct from an array, we would need to manually set the array's value to some other one, e.g. set s[0] = 0 ?
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
In the case above, once I do s[0].destroy() , will the value of z[0] change when the id is recycled for a "new" struct?
Yes, because it's just a pointer, implemented as an integer, and it's not that smart. Don't destroy structs you still intend to point to and you won't have to worry about such details.
No, the value of z[0] will never change, the object which z[0] points to will change, but z[0] will still have the old value (the structs id).



Ah so to remove a struct from an array, we would need to manually set the array's value to some other one, e.g. set s[0] = 0 ?

Doesnt matter if its an array or a simple variable, but destroying an object NEVER influences the variable the object is stored in, it only influences the object itself.

Its like this:
If you instantiate a struct to create a new object, the new object has a internal "id" which is also returned by the ".create()" method:
JASS:
local MyStruct a = MyStruct.create()
// now a is actually an integer variable which contains the id of the created object, for example 25
local MyStruct b = MyStruct.create()
// this would be id 26
// and so on...

If you call a structs method
JASS:
local MyStruct a = MyStruct.create()
call a.doSomething()
then internally a function which represents the method is called and the id of the object (a) is passed as an argument.
Like this:
JASS:
call myStruct_doSomething(a)

So variables of struct types are really just integers which contain the "id" of a struct.
Now if you destroy a struct object by calling "a.destroy()" all that happens is that the MyStruct object with the id "a" is destroyed, but the variable "a" itself is NOT changed (it still contains the value 25). But, the id "25" is internally marked for recycling and if you create a new object of that struct it might get the id "25" too.

I hope that made it clearer?


Ah so to remove a struct from an array, we would need to manually set the array's value to some other one, e.g. set s[0] = 0 ?
Again i dont understand why you are using arrays here, it doesnt make a difference whether you store an object in a variable or in an array.
To your question: You dont have to set the variable to 0 manually, it really doesnt change anything. The only reason why you would do that is if you want to use "object == 0" checks to check if an object exists (but thats quite uncommon).
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Again i dont understand why you are using arrays here, it doesnt make a difference whether you store an object in a variable or in an array.
To your question: You dont have to set the variable to 0 manually, it really doesnt change anything. The only reason why you would do that is if you want to use "object == 0" checks to check if an object exists (but thats quite uncommon).

Well I have a struct which represent a hero, and then I need a list of all these structs so I can find particular values about a hero (e.g. the Shadow Hunter learns hex at lvl 3). Arbitrary information which no native function can provide (because the heroes do not actually have any abilities, I just add them).

Yes, I need to check if an object exists in the array so I know if its a free slot.

Just to make sure, no struct is assigned an id of 0 (an array of struct has all its cells/members by default at 0)?

Here is my understanding again.

JASS:
struct MyStruct
endstruct

MyStruct array s 
MyStruct array z
s[175] == 0 //this is true
local MyStruct m = MyStruct.create()
set s[150] = m
set z[110] = m
s[150] == z[110] //will return true
local MyStruct n = MyStruct.create()
set z[10] = n
s[150] == z[10] //will return false
call m.destroy() //can we still reference m even after calling destroy on it?
s[150] == z[110] //will still return true
set s[150] = 0 //if s[i] == 0, it means it's a free cell in the array
s[150] == z[110] //will return false
...
local MyStruct w = MyStruct.create()
z[110] == w //possibility that w took the place of the struct 
                 //that z[110] originally pointed to
                 //this could return true or false
 
Last edited:
Well I have a struct which represent a hero, and then I need a list of all these structs so I can find particular values about a hero (e.g. the Shadow Hunter learns hex at lvl 3). Arbitrary information which no native function can provide (because the heroes do not actually have any abilities, I just add them).

Why don't you do something like this?

JASS:
struct Ability
    integer id
    thistype next
    thistype prev
endstruct

struct ShadowHunter
    Ability firstAbility
endstruct

Yes, I need to check if an object exists in the array so I know if its a free slot.

I don't understand why you're trying to manage your allocation when JassHelper generates the code for you. You may as well not use structs at all.

Just to make sure, no struct is assigned an id of 0 (an array of struct has all its cells/members by default at 0)?

That's correct, but you didn't need to know this either. I used jass for years and when I couldn't remember where struct indexing starts I just used -1 to be safe.

Edit: I shouldn't encourage that kind of behavior, you did the right thing actually by asking.

Here is my understanding again.

JASS:
struct MyStruct
endstruct

MyStruct array s 
MyStruct array z
s[175] == 0 //this is true
local MyStruct m = MyStruct.create()
set s[150] = m
set z[110] = m
s[150] == z[110] //will return true
local MyStruct n = MyStruct.create()
set z[10] = n
s[150] == z[10] //will return false
call m.destroy() //can we still reference m even after calling destroy on it?
s[150] == z[110] //will still return true
set s[150] = 0 //if s[i] == 0, it means it's a free cell in the array
s[150] == z[110] //will return false
...
local MyStruct w = MyStruct.create()
z[110] == w //possibility that w took the place of the struct 
                 //that z[110] originally pointed to
                 //this could return true or false

Assuming this is the only script which invokes MyStruct, and your ellipsis ... is the only time the script becomes unsynchronized, yes.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
vJass is just a jass preprocessor, which means all things added use only jass features.
Structs are basically just a bunch of global arrays.
Check the file outputwar3map.j generated when you save the map, and all your questions will be answered.
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
Thats a rather painful way to learn how structs work.

Here is my understanding again.

JASS:
struct MyStruct
endstruct

MyStruct array s 
MyStruct array z
s[175] == 0 //this is true
local MyStruct m = MyStruct.create()
set s[150] = m
set z[110] = m
s[150] == z[110] //will return true
local MyStruct n = MyStruct.create()
set z[10] = n
s[150] == z[10] //will return false
call m.destroy() //can we still reference m even after calling destroy on it?
s[150] == z[110] //will still return true
set s[150] = 0 //if s[i] == 0, it means it's a free cell in the array
s[150] == z[110] //will return false
...
local MyStruct w = MyStruct.create()
z[110] == w //possibility that w took the place of the struct 
                 //that z[110] originally pointed to
                 //this could return true or false

correct. gratz!

call m.destroy() //can we still reference m even after calling destroy on it?
Only, if the structs id isnt recycled yet (which wont happen until a new instance is created). But even if it works, abusing such things is a very bad coding style, you shouldnt do that :p
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Thats a rather painful way to learn how structs work.

Well, i'm not a speedfreak (but i was one long time ago when my knowledge was poor).
But i consider that knowing how vJass features are converted in jass is not an option.
And the fact is that he shouldn't have asked all these questions if he knew it.
 
Status
Not open for further replies.
Top