Types and 'the penny dropping'
BlitzMax Forums/BlitzMax Beginners Area/Types and 'the penny dropping'
| ||
Things are at last becoming clearer with how blitzmax handles types compared to b3d and bplus. I've been having a play: Type testtype Field x:Byte End type Local a:testtype=New testtype FlushMem Print "mem allocated at start = "+MemAlloced() For Local d=1 To 5000 a=New testtype a.x=d FlushMem next Print "after 5000 NEW testtypes = "+MemAlloced() FlushMem Print "flushed mem = "+MemAlloced()Although the loop here seems to suggest there are 5000 NEW types being made, only one exists. The a:testtype is being overwritten time and time again. This took a while to sink in. Under b3d and bplus there would in fact be 5000 new types being handled internally. Now I understand why we need to throw these types into a linked-list. This is blitzmax's way of keeping hold of the types .. a bit like pegging em all up on a washing line. |
| ||
Aren't you just creating one because of the Flushmem in the loop? |
| ||
I don't like the new way because I am an artist. I like to keep shit simple. Of course I'll have to learn all this new stuff, but to tell us, the users, that blitzmax is in any way simpler, is a joke. |
| ||
Aren't you just creating one because of the Flushmem in the loop? Yup. Add in a=null before the final flushmem and print and you'll have got rid of that one too. I don't like the new way because I am an artist. I like to keep shit simple. I'd have liked an option to turn off garbage collection, but I guess that's not possible because Blitz depends on it deep in the modules. Like you, I don't really see why it had to be changed. If I didn't need any helping creating a resource and allocating memory for it, I don't see why it's particularly hard work to clean up after myself. I assume there's more to it, and again, perhaps it's because of the way BMax works internally. |
| ||
Umm ... doesn't Flushmem only get rid of `unused` variables, so since you are using the `a` variable it wouldn't flush it anyway? Also, it does make sense that if you make a= something, any further instances of a= is going to overwrite the contents of a with something new, so if you use a to create a type there is only one intance of a tied to the type. Doing `New` would just overwrite it. Although, I can see your point, you might think that it creates a bunch of new types that you just don't keep track of. But I guess it's better to keep track by tying it to the variable. |
| ||
Think "reference count": assigning a new instance to "a" decrements the ref count on the prev instance to zero. It's in a "ready-to-delete" state waiting for a flush mem. So in practical terms it doesn't exist and you only ever have one, ie, the one assign to "a" which will have a ref count = 1. |
| ||
erm... If x in the Type is declared as a Byte, then I don't see how it can be assigned d, which in that code would default to an Int ? Tom |
| ||
Hey, good point thats odd 0_o according to the bmax docs you shouldn't be able to imply that conversion due to possible data loss. |
| ||
When a is assigned to a new object, it is no longer pointing to the last one. Since nothing's now pointing to the last one, it gets freed. |
| ||
Hmm that could be a pain in the arse tbh. Like in b3d you might have a list of type a like a\life a\image and so on. and just by calling a.mytype = new mytype it would auto add it to the LIST a ? so is this not the case with max ? if not does that mean that to do the above b3d code you will have to actually code and manage traverse our own linked lists ? if so im not so keen on that at all. |
| ||
and just by calling a.mytype = new mytype it would auto add it to the LIST a ? so is this not the case with max ? No but it's easy to get Max to behave like classic Blitz .. Global list:TList=CreateList() Type nametype Field name$ Method New() ListAddLast list,Self End Method End Type Local n:nametype n=New nametype n.name="Tom" n=New nametype n.name="Amanda" n=New nametype n.name="Mary" n=New nametype n.name="Peter" For n=EachIn list Print " -> "+n.name Next Input "Done. Return to end ..."In the above code when I do n=New nametype the 'Method New() .. End Method' bit is executed automatically. Since I have 'ListAddLast list,Self' in there the type gets placed in the list without hassle. |
| ||
Is there any reason not to include the list in the type definition? |
| ||
From the above example, placing the list definition inside the type would prevent this part from working:For n=EachIn list ... NextBecause the 'list' would only be global to the type itself. I could do it this way though .. Type nametype Global list:TList Field name$ Method New() If list=Null list=CreateList() ListAddLast list,Self End Method Method ShowList() For Local n:nametype=EachIn list Print " -> "+n.name Next End method End Type Local n:nametype n=New nametype n.name="Tom" n=New nametype n.name="Amanda" n.showlist Input "Done. Return to end ..." |
| ||
No, List is a variable:Global list:TList=CreateList()TList is the class name. |
| ||
Once advantage of keeping the list global is the fact that you can throw different types in there. Look .. cats and dogs living in harmony: Global list:TList=CreateList() Type cattype Field name$ Method New() ListAddLast list,Self End Method End Type Type dogtype Field name$ Method New() ListAddLast list,Self End Method End Type Local c:cattype Local d:dogtype c=New cattype c.name="Felix" c=New cattype c.name="Garfield" d=New dogtype d.name="Rover" d=New dogtype d.name="Tyson" Print "Cats:" For c=EachIn list Print " > "+c.name next Print "Dogs:" For d=EachIn list Print " > "+d.name next Input "Done. Return to end ..." |
| ||
neat! |
| ||
Ahh in the cats&Dogs one, your actually creating two lists inside one list variable ?? if so thats cool as FK, would mean you can have say for example a List for all spaceships, then inside that list you can actually have lists of all alien.shaship or lists of all player.spaceships Thats minted. I was just buggin out cos I thought I was going to have to do all my own linked list and binary tree managment code. but seems like its all there just changed the way its used. sweet. |
| ||
I'm getting a listaddlist error it dont know what listaddlist is.' Strict Global GFX_Width : Int = 800 Global GFX_Height : Int = 600 Global GFX_Depth : Int = 16 'Graphics GFX_Width,GFX_Height,GFX_Depth Global SpaceObjectList:Tlist = CreateList() Type SpaceObject Field pos_x : Int Field pos_y : Int Field Velocity : Int Field name : int Method New () listaddlist SpaceObjectList,Self End Method Function Display_New() Print "A New Space Object was Created." cls End function End Type Type Planet Extends SpaceObject Field Image:Timage End Type Type Moon Extends SpaceObject Field Image:Timage End Type Type Star Extends SpaceObject Field Image:Timage End Type While Not KeyHit(KEY_ESCAPE) Cls FlushMem;Flip wend the error I get is something like unkown listaddlist What am I doing wrong here.. |
| ||
From the above example, placing the list definition inside the type would prevent this part from working: For n=EachIn list ... Next Well yeah, but you'd only have to reference the list correctly with NameType.List instead of just list, surely? I realise there are situations where you might not want to put the list in the type definition, I just wondered if there was a general reason not to, because that's the way I've been doing it so far. Yavin : It's ListAddLast |
| ||
OH FFS - /me walks off ina huff and kicks himself a few times. Now thats a good case against dislexic people being programmers. I must have read over that code about 10 times and my brain just kept on reading it out as listaddlist .. I actually just noticed it and came through to the laptop to post a DOH , but you beat me to it lol.. Must admit though I am likin max. |
| ||
I hate when that happens. :) |
| ||
In the cats and dogs example, the list contains both cats and dogs, the magic is in the " for d = eachin list ". A list contains Objects, and cats and dogs are implicitly subtypes of Objects. Since d is typed to be a dog, then it cannot be assigned to be a cat, so the for...eachin loop can only operate on dog instances in the list. In fact, if you wanted to make blitzmax even more like the original blitz, I suppose you could replace all of these: for m.myType = each myType with: for m:myType = eachin list (Just as long as you make sure to include the type information) But it might be quite slow, since list would contain every single instance of your types! |
| ||
An extended version of the cats&dogs+owners. I don't think the debugger can handle nested structures (try expanding the "_value" field).Type pettype Global pets:TList Field name$ Field ptype$ Method New() If Not pets pets=CreateList() ListAddLast pets,Self End Method End Type Type cattype Extends pettype Method New() ptype="Cat" End Method End Type Type dogtype Extends pettype Method New() ptype="Dog" End Method End Type Type owner Global owners:TList Field pets:TList Field name$ Function AddOwner:owner(n$) Local o:owner = New owner o.name = n Return o End Function Method New() If Not owners owners=CreateList() ListAddLast owners,Self pets=CreateList() End Method Method AddDog:dogtype(n$) Local p:dogtype = New dogtype p.name=n ListAddLast pets,p Return p End Method Method AddCat:cattype(n$) Local p:cattype = New cattype p.name=n ListAddLast pets,p Return p End Method End Type Local o:owner Local c:cattype Local d:dogtype Local p:pettype o = owner.AddOwner("Mickey") o.AddDog("Rover") o.AddCat("Felix") o = owner.AddOwner("Minnie") o.AddDog("Fido") o.AddCat("Garfield") Print "Owners:" For o=EachIn owner.owners Print "Owner: "+o.name For c=EachIn o.pets Print "~tCat: "+c.name Next For d=EachIn o.pets Print "~tDog: "+d.name Next Print "~tAll:" For p=EachIn o.pets Print "~t~t"+p.ptype+": "+p.name Next Next Print "" Print "Pets:" For c=EachIn pettype.pets Print "~tCat: "+c.name Next For d=EachIn pettype.pets Print "~tDog: "+d.name Next Print "~tAll:" For p=EachIn pettype.pets Print "~t~t"+p.ptype+": "+p.name Next Print "" DebugStop |