Jump to content


Structures


  • This topic is locked This topic is locked
70 replies to this topic

#41 gnysek

gnysek

    GMC Member

  • GMC Member
  • 318 posts
  • Version:GM:Studio

Posted 06 February 2011 - 10:54 PM

Wow...I can't begin to tell you how slow your ds_map() accessors are :). Besides, there's nothing saying you can't then store your structure object in a ds_map() or something, but it would mean many times less accessing to get your data. Basically, you'd just make a single struct, and add THAT to your global.resources map. This is far, FAR quicker to run, and would use a lot less memory. Win, win in my book.


Yes, that's why structures are good idea :D But I still need to use ds_map, because my keys are names of sprites, so when I'm using sprite_index = ResourceLoad('abc'); it checks for key 'abc' in global.resoucres ds_map, and loads image 'abc.png' from hard disk, or returns it's reference when it's loaded. I cannot use global.resources['abc'], which reffers to struct. (ofc I'm using this script only in create event, but it helps me to have 0 sprites inside GMK file, and very light .exe).
Also when I need to store data of players, or enemies on map in array, I still need to allocate more indexes than it's really needed, if one of them is no longer available on map, which really annoying me.

Some things should be extended for usage of struct with arrays: a) associative arrays, or B) as in PHP, when you write $a[11] = 1; $a[14] = 6; there will be really two elements in array, not 15 as it's now, and there will be possibility to count them and make foreach(index,value in array) ;) Because idea of storing struct in array is really good, but for now it giving to little possibilities :D

Edited by gnysek, 06 February 2011 - 10:54 PM.

  • 0

#42 Gamer3D

Gamer3D

    Human* me = this;

  • GMC Member
  • 1589 posts
  • Version:GM8.1

Posted 06 February 2011 - 10:59 PM

Theophilus, here are your explanations:
Spoiler


But yeah. I think structures are a great idea. They would need more thought to permit useful sorting within structures.

Code constants could be helpful, possibly confusing for new users (if someone uses them in a tutorial).

Enumerated types... eh. Without strict types, users might as well use constants.
  • 0

#43 sabriath

sabriath

    12013

  • GMC Member
  • 3147 posts

Posted 06 February 2011 - 11:04 PM

1. Based on my previous idea, you can easily add in a radial option to choose between struct/enum/whatever (just as you decide between self/other for code).

2. I do not see the point in having structures if you do not add methods for them...honestly. ragarnak has stated that it is nothing more than a ds_list and you brushed him off....but look at this:

//constant values
experience = 0
nextexp = 1
level = 2


//create a "structure"
Player = ds_list_create();
  ds_list_add(Player, 0);   //experience
  ds_list_add(Player, 100); //nextexp
  ds_list_add(Player, 1);   //level

//checking a member
playersexp = ds_list_find_value(Player, experience);

Obviously there is a lot of coding, but it's essentially the same thing. If you add in the fact that you state DS is going to be made easier to code, then the "lots of coding" is a moot point.

You can even add in pointers to other lists, which could be other structure formats...so you could end up with a double-linked list if you wanted, all with ds_list (I know, I've done it with my 39dll lib). Again, without methods for structures, I see no point other than making it "look" fancier.

3. Placing the structure definition in-line with code is bad in my opinion. How I visualize code (whether in script or object) is that they are function calls made by the GM engine...and you don't see structures/classes in C defined in functions for global use do you? This just stinks of teaching bad programming habits for beginners if they decide to move to another language (unless your sole purpose is to ensnare, like BYOND did with it's haphazard direction).



edit: Come to think of it, you could combine them with scripts (instead of changing the gmk format) and just have another radial option that selects whether it is a script or structure/enum/whatever. Since all of them contain the same editor type, might as well. I still think they should be a separate resource type, but seeing that you are looking for suggestions on 8.1 and not 9.0, combining them with scripts won't break anything.

Edited by sabriath, 06 February 2011 - 11:13 PM.

  • 0

#44 TheMagicNumber

TheMagicNumber

    GMC Member

  • GMC Member
  • 5247 posts
  • Version:Unknown

Posted 06 February 2011 - 11:26 PM

Structs, enums, and constants in code. Yes, as long as it will syntax highlight and work with the code completion.

Using struct_create() to initialize a structure is a bit long and ugly. Maybe something like the new keyword in other languages, instead.

Also, I hope garbage collection is being worked on. :)
  • 2

#45

  • Guests

Posted 06 February 2011 - 11:36 PM

Sabriath I think your missing the point. Sure, I could (and currentlt DO) achive structures in different ways - I use multiple arrays myself, but thats horrible, simply horrible. Wanting to use maps or lists for them is even nastier. Just because you CAN currently do it another way, doesn't mean it's any good.

As to not defining them in code... Well, I've yet to see any evidence to it being inconsistent with the rest og GML, particually if we allow scoping (instance, var and global), in which case it's the same as everything else. However, like any new feature, you won't have to use it until you see a benifit yourself.

I also strongly disagree it's a bad thing to teach. I learnt it back in assembler days because it gave me some serious felxibilty into how I visualised my data. Part of the problem with most folk these days is they don't "really" know how data is stored, and as such they waste LOADS of memory, and hence speed. Memory bandwidth is a killer, and if you don't know your data, your burning performance. Classes (and objects) hide a lot of sins, simple structs let you fine tune your data. So just like your ds_map example, your hiding lots of issue, and just assume it should run quickly and be memory efficient. This is hardly ever true.

So until someone gives me a hard and fast reason as to why we shouldn't (like the Mac issue), I don't see any reason not to add it....

#46 paul23

paul23

    GMC Member

  • Global Moderators
  • 3355 posts
  • Version:GM8

Posted 06 February 2011 - 11:36 PM

I'm just wondering: how are structures going to get passed around, by reference or by value?

struct A {
   name = "paul"; //would default value be allowed? - I think it should..
};
var1 = struct_create(A);
var2 = var1;
var2.name = "ruud";
//now what's is the "var1.name"?
And more subtle, in a script:
argument0.name = "ruud"; //supposed argument0 is the unchanged structure, what happens to the structure outside the script?
If passing by reference you shouldn't forget a duplicate function.. (And maybe some kind of easy "pass by value sign" for scripts?)
  • 0

#47 Smarty

Smarty

    GMC Member

  • Retired Staff
  • 7213 posts
  • Version:GM:Studio

Posted 06 February 2011 - 11:39 PM

2. I do not see the point in having structures if you do not add methods for them...honestly.

Because they wouldn't be structs anymore, they'd be classes. And that's a considerably more complex kind of entity, especially when it comes to scoping variables and methods, or when features such as inheritance are introduced.
  • 0

#48 LSnK

LSnK

    NaN

  • GMC Member
  • 1188 posts

Posted 06 February 2011 - 11:49 PM

I do not see the point in having structures if you do not add methods for them...honestly.

Ever hear the phrase "Perfection is the enemy of the good"? It's silly to reject an incremental improvement because of minor deficiencies. We can make clumsy workarounds for any possible feature, it's not a reason to drop them.
  • 0

#49 sabriath

sabriath

    12013

  • GMC Member
  • 3147 posts

Posted 06 February 2011 - 11:58 PM

Sabriath I think your missing the point. Sure, I could (and currentlt DO) achive structures in different ways - I use multiple arrays myself, but thats horrible, simply horrible. Wanting to use maps or lists for them is even nastier. Just because you CAN currently do it another way, doesn't mean it's any good.

I wasn't saying that because you can do it another way that it shouldn't be implemented...but what I said was that the underlying performance used on a ds_list will be virtually the same exact thing as adding structures without methods. Unless you plan to revolutionize the way GM does it's variables, I'm looking at it from the standpoint of structures being nothing but an object that is not placed on the event queue. This means that variables can be "created" on the object by adding it to the name map, and when reading the value, it searches the map for name->pointer and returns the GMVALUE for it.

Compare that to a ds_list, which is exact in its nature of WHICH element you are choosing and updating, which means you go from a O(log) to an O(1) method of search. The downside is that you must read and write separately (so you cannot do += ), so other than the ease of the eyes for source code, I am not seeing how performance will be improved on the matter.

As to not defining them in code... Well, I've yet to see any evidence to it being inconsistent with the rest {of} GML, {particularly} if we allow scoping (instance, var and global), in which case it's the same as everything else. However, like any new feature, you won't have to use it until you see a {benefit} yourself.

The benefits of using a ds_list outweigh that of the hypothetical structure (in performance) that you are suggesting based on the assumption of your remark of:

So... while structs do behave somewhat similar to objects/instances in terms of storing data, you won't have functions/events associated with them, and they will use far, FAR less memory.


I also strongly disagree it's a bad thing to teach. I learnt it back in assembler days because it gave me some serious felxibilty into how I visualised my data. Part of the problem with most folk these days is they don't "really" know how data is stored, and as such they waste LOADS of memory, and hence speed. Memory bandwidth is a killer, and if you don't know your data, your burning performance. Classes (and objects) hide a lot of sins, simple structs let you fine tune your data. So just like your ds_map example, your hiding lots of issue, and just assume it should run quickly and be memory efficient. This is hardly ever true.

I never said that 'structures' were a bad habit to teach...what I said was 'implementing structures in function code' is a bad habit to teach. Obviously structures are an almost necessity in programming, but putting it in GML forces the interpreter to run over the structure before it builds it in memory...which means it is no longer seen as a resource (and from what I can envision, cannot be exported/imported). I am only suggesting that it be initialized separate from GML coding styles.

However, since most of how GM works is self-interpretive (execute_string/file/etc.), here are some added ideas to make structures code in GML (similar to how object_add works):

stats = structure_create();
  structure_add_variable(stats, "experience", 0);
  structure_add_variable(stats, "nextexp", 100);
  structure_add_variable(stats, "level", 1);
  structure_add_method(stats, "gain", "experience += argument0; if(experience >= nextexp) level += 1;");

PlayerStat = stats.new();
PlayerStat.gain(104); //yay, level up


So until someone gives me a hard and fast reason as to why we shouldn't (like the Mac issue), I don't see any reason not to add it....

I never said you _shouldn't_ add it....I'm clarifying my suggestion that you should change _how_ to add it.


Because they wouldn't be structs anymore, they'd be classes. And that's a considerably more complex kind of entity, especially when it comes to scoping variables and methods, or when features such as inheritance are introduced.

Structures, enums, and even unions can have methods....it is not limited to classes.

Edited by sabriath, 06 February 2011 - 11:59 PM.

  • 0

#50 Big J

Big J

    GMC Member

  • GMC Member
  • 2818 posts
  • Version:GM8.1

Posted 07 February 2011 - 12:28 AM

Structures sounds good to me, especially if they're optional. Defining constants in code would also be super awesome. The only problem I see is user-defined constants no longer being color-coded in code editor. But I suppose that's minor.
  • 0

#51 thenoller

thenoller

    GMC Member

  • GMC Member
  • 208 posts

Posted 07 February 2011 - 12:30 AM

I am myself a (maybe just above but pretty much) average GML-user. All I know about structures, I've read in this topic, and I have to admit that it would be a pretty damn ingenious element to add.

I just hope that the more professional multi-language users remember that GML still have to maintain some sort of internal logic, regardless of how structures work in other languages..

Because of their similarities with arrays, a syntax like this would make most sense to me:
/*When what looks like an array is initialized with a string,
the given value is stored with that string as its "key",
thus extending the functionality of the regular 1- and 2D-array.*/
player1['stats_power']=18;
player1['stats_maxhp']=24;

player1['name']='Mark';
player1['hp']=20;
player1['class']=CL_RANGER

player2['stats_power']=20;
player2['stats_maxhp']=22;

player2['name']='Jeff';
player2['hp']=17;
player2['class']=CL_DESTROYER

I do see the problem with not being able to initialize other array's inside of the structure/super-array, as opposed to objects. If structures are added to GM9 (or whatever) and the syntax ends up being...
player1 = ds_structure_create();
player1.name='Mark';
player1.hp=20;
//etc..
...then maybe 'structures' should simply be called something like 'data-objects' or whatever, to establish the their function as objects without events.

Just some humble suggestions..
  • 0

#52 111Studio

111Studio

    GMC Member

  • GMC Member
  • 258 posts
  • Version:GM:Studio

Posted 07 February 2011 - 12:33 AM

I see your point Sabriath.

I currently use scripts as functions or as you call them "methods" to access array information. Having the ability to have those dedicated and defined within a structure would be really nice, but I think the point of structures is how simple they are as simply accessing groups of data with ease and no extra unused memory. It would be easy to write a function accessing structure data using scripts, although in that case it'd really be nice to have pointers.
  • 0

#53 Smarty

Smarty

    GMC Member

  • Retired Staff
  • 7213 posts
  • Version:GM:Studio

Posted 07 February 2011 - 12:36 AM

Structures, enums, and even unions can have methods....it is not limited to classes.

Actually, the reason that in some languages they're possible on other entities than classes is because they have in fact become classes themselves. But you're missing the point. The difference is in the implementation - structs may be introduced relatively easily as they're a kind of compound variables, but this isn't the case for classes. Mike already mentioned the difference in how they're handled. It's a clear distinction, in spite of that a couple of languages that have made it a bit of a gray area.

YYG aren't stepping up that bridge yet. Classes are a discussion to be held in the future.

Edited by Smarty, 07 February 2011 - 12:37 AM.

  • 0

#54 Charlie2531games

Charlie2531games

    GMC Member

  • New Member
  • 11 posts

Posted 07 February 2011 - 12:59 AM

Here's my idea for the code for structures. Don't tell me it's bad if it is. I'm not the best at GML.
const INST_strc = 5  //tells game maker 5 instances 

var variable; //creates/sets the variable in use

variable = 1/strc //sets the variable to a given ammount and then gives it the 5 instances



strc; //tells game maker that it is about to add the 5 instances

{

    1; = 0 //instance 1, what it equals

    2; = 0 //instance 2, what it equals

    3; = 0 //instance 3, what it equals

    4; = 0 //instance 4, what it equals

    5; = 1 //instance 5, what it equals

}



    (const INST_strc; create) //creates/sets the instances

  • 0

#55 Rusky

Rusky

    GMC Member

  • New Member
  • 2450 posts

Posted 07 February 2011 - 03:04 AM

Structures with statically-defined fields don't seem like a good fit for Game Maker, and they introduce a lot of unnecessary complexity due to how GM is already set up scope-wise. The functionality is already there so there's no reason to just pile on another disjoint feature that doesn't match with how the rest of the language works.

I think a better idea, especially considering the recent discussion on data structure syntax, would be to follow other dynamic languages like Python, Ruby, PHP and JavaScript. The functionality offered by ds_map and objects themselves is nearly identical to dictionaries, objects and associative arrays in these other languages.

Why not just make "structures" simplified objects i.e. without code, participation in the event loop or built-in variables, but with dynamically-created fields? It might look something like this:
var foo = ds_map/struct/dict_create()
foo.bar = 3
foo.baz = "hello world"
foo["quux"] = ds_map/struct/dict_create()
foo.quux.copy(some_other_ds_map/struct/dict)
If ds_maps are inefficient, optimize them- languages like the ones I listed are used in performance-sensitive applications and their bottlenecks are not member access.

Other than slightly faster field access, which is dwarfed by other inefficiencies, often optimizable and whose overhead is small enough that major languages like the ones I listed are perfectly okay with it, there is absolutely no reason to add yet another concept to GML when what's already there is more consistent and, with some modification to its notation, just as or even more convenient.

Edited by Rusky, 07 February 2011 - 03:05 AM.

  • 1

#56 ~Dannyboy~

~Dannyboy~

    ~hoqhuue(|~

  • GMC Member
  • 2144 posts
  • Version:GM8

Posted 07 February 2011 - 03:09 AM

As to not defining them in code... Well, I've yet to see any evidence to it being inconsistent with the rest og GML

I don't think defining it in code is inconsistent with the rest of GML, but I think the example you gave in the first post is.

Struct's seem to me to be a new type of resource. As such, they should be added in the same way as other resources:
UndoSlot = struct_add();
struct_member_add("Rank");
struct_member_add("Suit");
struct_member_add("Stack");
struct_member_add("Active");

MyArray[0] = struct_create( UndoSlot );

MyArray[0].Rank = 1;
MyArray[0].Suit = CLUBS;
MyArray[0].Stack = 3;
MyArray[0].Active = true;

Or allow other resources (especially objects and scripts) to be defined in GML in a similar manner to the example syntax you posted.

EDIT: I like Rusky's point about dynamic structs, they seem much more fitting to GML than static structs. I imagine this would look more like:
MyArray[0] = struct_create();

MyArray[0].Rank = 1;
MyArray[0].Suit = CLUBS;
MyArray[0].Stack = 3;
MyArray[0].Active = true;

Edited by ~Dannyboy~, 07 February 2011 - 03:13 AM.

  • 0

#57 kburkhart84

kburkhart84

    GMC Member

  • GMC Member
  • 1606 posts
  • Version:GM:Studio

Posted 07 February 2011 - 03:32 AM

I wouldn't mind having the constants be defined in code, but as another user said, I still want them to be usable with intellisense.

I don't have but one thing against the GUI for constant definition. I want to be able to define "groups" of them. Like I mentioned in the other post, I use contants a lot, mainly to avoid hard coding anything where possible. If I had that feature, I might not care so much for using a code window to define constants.
  • 1

#58 Derme

Derme

    GMC Member

  • GMC Member
  • 277 posts
  • Version:GM:Studio

Posted 07 February 2011 - 09:05 AM

I have to agree with one of the previous posts, can't wait for GM9. ;)

With regard to the Define Constants menu, I too hate it.What I would like instead is a guaranteed "Main" like script that I can create and know that it executes at game startup. This would create a logical place to put my const, struct and any other initialization code.Currently, the popular technique seems to be create a start-up room, with the sole purpose of running an initialization script, and then start the first game play room. Awkward.

Lastly... in terms of the 8.1 thing. We will be fixing bugs as well as doing new features, and yes... lots of this will relate to further down the line (i.e. not 8.1), but we hope many will come in before 9.0.

I'm concerned that the GM Windows (8.x) will diverge to much from GM4Mac (7.x). As it stands now, the preferred development platform for those with both is Windows, then use LGM to create a file format compatible source loadable with GM4MAC. The conversion between PNG and GIF is inconvenient, but the rest is really no big deal.With these anticipated 8.x changes, the differences between Mac and Windows platforms will start to become so significant that porting to Mac will become less feasible.


I always forget to use constants, if they were in a #Main script it wouldn't just be useful to define constants, but also a number of other things.

Enums, Yes. I vote for the C# version, to keep it simple. Would be so quick to type to.

Now, structures, another vote of approval here. Very simple and would make coding much easier.

@Slayer64, I can't see what your argument against structures is, not only is it faster than using objects it is optional, so I can't see any reason why they couldn't be added.

Edited by Derme, 07 February 2011 - 09:06 AM.

  • 0

#59 sabriath

sabriath

    12013

  • GMC Member
  • 3147 posts

Posted 07 February 2011 - 09:41 AM

~Dannyboy~ : that's almost exactly what I had in my last post (the code)...by making structures similar to ds_* constructions.

I honestly feel that putting class declarations in GML is inconsistent because look at this for example:

//obj_dummy create event

struct something
{
  dx, dy;
}

But:

1. 'something' is not stored in intellisense when you create structures in other objects (so no colors to denote it as a usable resource). If you pre-parse, then what happens when you delete the structure or change the name? Now you have ghost patterns (VC does this sometimes), and you waste time constantly rechecking programmer code.

2. 'something' is now in-line code, not a resource...so you cannot import/export it (if you make structures with methods, it would come in handy for export/import ability)

3. you have to dedicate to initialization to ensure that all structures are defined before they are "created". Although this isn't much of a problem because most games do initializations anyway...but it would become a headache to code all structures in one spot (hopefully you don't accidentally delete the room/object that contains all your precious structures).

4. it's not the 'GM way' in my opinion. You state that structures are just like objects but without events (so it saves performance and space). If this is true, then think of what a person does to create an object:

Click 'Create Object' button
Name the object
Click 'Add Event' -> 'Create'
declare variables and their initial state for the object
etc. etc.

So wouldn't it and shouldn't it be the same for structures as well?

A person should click a 'Create structure/enum/wtfever' button
Name the struct/enum/whatever
Click 'Add Variable' -> Choose 'Static', 'Private', or 'Public'
name the variable and possibly set the initial state for it
etc. etc.

The same should go for the code style used in creating structures on-the-fly (just as you create objects), as I have already mentioned:

stat = structure_create();
  structure_add_var(stat, st_public, "experience", 0);
  structure_add_var(stat, st_public, "nextexp", 100);
  structure_add_var(stat, st_public, "level", 1);



I've put my 2 cents in....do what you want though, it's your baby now.
  • 0

#60 paul23

paul23

    GMC Member

  • Global Moderators
  • 3355 posts
  • Version:GM8

Posted 07 February 2011 - 10:23 AM

stat = structure_create();
  structure_add_var(stat, st_public, "experience", 0);
  structure_add_var(stat, st_public, "nextexp", 100);
  structure_add_var(stat, st_public, "level", 1);



I've put my 2 cents in....do what you want though, it's your baby now.

Problem with "creating structures" on the fly is that it becomes pretty hard to understand: similar to objects and instances, you have structures (and objects? not sure which term would apply here)..

So you would have 2 "structure_create(...)" functions.. (1 to declare a new structure, 1, which takes a structure as argument and actually creates the container).
stat = structure_create();
  structure_add_var(stat, st_public, "experience", 0);
  structure_add_var(stat, st_public, "nextexp", 100);
  structure_add_var(stat, st_public, "level", 1);
mystruc = structure_create2(stat);
show_message(mystruc.level);
So much for preventing typing, and actually increasing the difficulty:
stat = structure_create();
  structure_add_var(stat, st_public, "experience", 0);
  structure_add_var(stat, st_public, "nextexp", 100);
  structure_add_var(stat, st_public, "level", 1);
stat mystruc;
show_message(mystruc.level);

btw: *WHAT* is the point of private variables if you don't have member methods? To store something which can't be retrieved in any way?
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users