b3d after command in bmax?
BlitzMax Forums/BlitzMax Beginners Area/b3d after command in bmax?
| ||
Hiya, I have the following code: For Local p:pointType = EachIn pointList Local p1:pointType = p Local p2:pointType = after p1 Next I want to make variables from P1 to P4 be 4 objects in the list so I can calculate some interpolated values... Basically there is no "after" command in bmax so I'm wondering how I get the object after p? and then the object after p2 and so on... I only need 4 of them. |
| ||
use an array instead of a list? |
| ||
I am using a list because it's essential to insert data at any point, so an array's not possible, thanks RiK. |
| ||
Method NextLink:TLink() 'Returns the next link in the list |
| ||
Can you tell me how to use it please. I can't figure out how to get it to work with the above code. I have already tried... |
| ||
This might help... nextlink and this... more nextlink and this... more more nextlink and more... blimey more nextlink and possibly this... Graphics 640,480,0 mylist:TList=CreateList() Type mytype Field count:Int End Type For Local x = 1 To 50 s:mytype = New mytype s.count=x ListAddLast mylist,s Next my_firstlink:TLink = mylist.firstlink() currentlink:TLink = my_firstlink s:mytype = mytype(my_firstlink.value()) mykey=37 While Not KeyHit(key_escape) Cls Select mykey Case key_left my_firstlink:TLink = mylist.firstlink() currentlink:TLink = my_firstlink s:mytype = mytype(my_firstlink.value()) DrawText "my_firstlink:TLink = mylist.firstlink() ; s:mytype = mytype(my_firstlink.value())",0,0 DrawText "my_firstlink count field = " + s.count, 0,10 Case key_right my_lastlink:TLink = mylist.lastlink() currentlink:TLink = my_lastlink s:mytype = mytype(my_lastlink.value()) DrawText "my_lastlink:TLink = mylist.lastlink() ; s:mytype = mytype(my_lastlink.value())",0,0 DrawText "my_lastlink count field = " + s.count, 0,10 Case key_up my_prevlink:TLink = currentlink.prevlink() If my_prevlink <> Null currentlink:TLink = my_prevlink s:mytype = mytype(my_prevlink.value()) DrawText "my_prevlink:TLink = mylist.prevlink() ; s:mytype = mytype(my_prevlink.value())",0,0 DrawText "my_prevlink count field = " + s.count, 0,10 Else DrawText "No prevlink. Current position : " + s.count,0,0 EndIf Case key_down my_nextlink:TLink = currentlink.nextlink() If my_nextlink <> Null currentlink:TLink = my_nextlink s:mytype = mytype(my_nextlink.value()) DrawText "my_nextlink:TLink = mylist.nextlink() ; s:mytype = mytype(my_nextlink.value())",0,0 DrawText "my_nextlink count field = " + s.count, 0,10 Else DrawText "No nextlink : Current position : " + s.count,0,0 EndIf Default DrawText "Invalid Selection. Current position " + s.count,0,0 End Select DrawText "Firstlink=left, lastlink=right, nextlink=down, prevlink=up",0,40 Flip FlushMem mykey=WaitKey() If mykey=27 Exit Wend |
| ||
A not so complicated example:Global List:Tlist = New TList Type TBase Field ID:Int End Type For x = 1 To 6 Local T:TBase = New TBase T.ID = X List.Addlast(T) Next Global T1:Tlink = List.FirstLink() For P:TBase = EachIn List P1:TBase = P T1 = T1.NextLink() If T1 <> Null Then P2:TBase = TBase(T1.Value()) EndIf Print P1.ID Print P2.ID Print "---------" Next |
| ||
Wow thanks lads! I didn't realise this popped up so many times. It's pretty obvious then, that blitzmax needs a proper after command! As it's clearly something a lot of people want to do with standard eachin loops as well! |
| ||
I have written 2 Functions that should be equal to After and Before. Here is the code: Type TBase Field ID:Int End Type For x = 1 To 6 Local T:TBase = New TBase T.ID = X List.Addlast(T) Next Global T1:Tlink = List.FirstLink() For P:TBase = EachIn List P1:TBase = P P2:TBase = TBase(After(List,P1)) P3:TBase = TBase(Before(List,P1)) Print P1.ID Print P2.ID Print P3.ID Print "---------" Next Function After:Object(List:Tlist,value:Object) Local T1:Tlink = List.FindLink(value) Local T2:Tlink = T1.NextLink() If T2 = Null Then Return List.FirstLink().Value() Else Return t2.value() EndIf End Function Function Before:Object(List:Tlist,value:Object) Local T1:Tlink = List.FindLink(value) Local T2:Tlink = T1.PrevLink() If T2 = Null Then Return List.LastLink().Value() Else Return t2.value() EndIf End Function I hope that this is what you was looking for. |
| ||
Perfect! A big thanks to you klepto2! :) Why didn't they have this built in? it makes every bit of sense for the high level programmer. |
| ||
I know I'm new to this'ere OO malarky but can't you just extend a base type?... |
| ||
It's pretty obvious then, that blitzmax needs a proper after command! It can't have what you call a "proper after command" as not all objects are stored in lists, or even sequential datastructures. In Blitz3D all objects had to be stored using linked lists. Thus all objects would inherently have next and previous objects. In BlitzMAX, this is no longer the case, not only can objects be stored in different lists, and data structures, but they can be stored in no datastructure at all. I have written 2 Functions that should be equal to After and Before. Functionally perhaps, but it will be much, much slower (Linear vs. Constant time complexity), particulary on large collections. Why didn't they have this built in? Huh? it makes every bit of sense for the high level programmer. No it doesn't. EachIn is a general purpose itterator, and returns the objects collected, in sequence. Not all collections (heaps and dictionaries for example) have data structures where data is stored linearly, and so being able to get the next and/or previous object in the collection may not make sense. |
| ||
whatever. |
| ||
I'd like to know more about how fast it is to iterate through arrays rearranging the order of every entry, compared to using linked lists. I've seen threads that compare the overall speed of arrays vs lists (arrays were much faster), but i don't remember if we looked at how long it takes to cut things out (or add things) to the middle of an array and move every entry in the array. You could write some functions to do it in a general way too. Anybody done any thinking on this? |
| ||
Flameduck is right on one point, the functions you wrote do emulate the after,before functionality however they are going to be slower (just based on the 'findlink' function). It would be quicker if fish learned how to use the links and lists rather than slow him down (app-wise) with wrapper functions to emulate b3d. It took me a bit of asking questions to figure out what you can do with a link and what you can do with a list. And I still have to go back and look at past source I wrote to remember how the whole thing works, but at least I can write it optimally and not have to rely on slow wrappers. Don't get me wrong klepto, they are very nice functions, they are just going to be slow. |
| ||
The simplest thing is to open brl.linkedlist bmx file in which the whole linked list source is which is quite simple to understand ... |
| ||
Hi, I actually find the list stuff murderously difficult to understand with almost no documentation. I don't actually have the luxury of time, so the after function posted above is an absolute life-safer, for which I am deeply grateful for. As we know, bmax is a multi levelled language. It has easy ways to do things and far more difficult but flexible ways to do things. Believe me I tried to learn the guts of lists but ended up coming away TOTALLY confused after hours and hours of effort. Thats half a days work, and I gave it a good shot. Some programmers intuitively grasp lists: what about people who have never used lists before? Or non advanced programmers? Believe me, it's *confusing*! Some people are better programmers than others. I really like after, and it works superbly in Blitz3D. I think judging by the above links, a lot of people want it :) |
| ||
Also absent: InsertAfter InsertBefore Perhaps these could get added to the next release of Blitzmax. |
| ||
I know that my Functions will be slow in comparison to the optimal way. These Functions should only be alternatives for beginners. And maybe they should show abit about how to use TLink with its Methods. And my Functions are based on the Valueatindex Method of Tlist. |
| ||
Also absent: InsertAfter InsertBefore Perhaps these could get added to the next release of Blitzmax. Insertbeforelink InsertAfterlink |
| ||
Doesn't make it faster at all. For fast next - before with lists you best make an array out of them (there is a simple command for that) and iterate through it. Thats constant access time no "search" as any linked list command will have to do. |
| ||
Insertbeforelink InsertAfterlink Don't work with objects do they? thats the whole point of this post - functions that work directly with objects for ease of programming and stuff - just like earlier blitz. |
| ||
Also absent: InsertAfter InsertBefore Did you read my previous post? |
| ||
Taken from here post somewhere on this site...Function InsertAfter(list:TList,a:Object,b:Object) Local link:TLink link=list.FindLink(a) Assert link Else "Can't find Object "+a.ToString()+" In List" list.InsertAfterLink(b,link) End Function t:TList=New TList t.AddLast "A" t.AddLast "B" InsertAfter t,"B","C" For a$=EachIn t Print a Next <edit> here it is and.. this |
| ||
Thanks lads, you've all been very patient with my stumbling around :) |
| ||
coming from a java background ... you have to be careful with iterators over collections and operations that modify the backing collection. said a different way, if you are iterating over a "collection of things", where the order of that iteration, and the "things" to be iterated over were organized in a particular way, and then *inside* the iterative loop, you muck around with the source collection, bad things can happen. in java, iterators can "fail fast" (throws an exception) if it is detected that this has happened. also, as others pointed out, most any collection can minimally support an iterator. some, may or may not support other types of operations such as insertbefore/insertafter etc ... again, coming from Java, and knowing some of the pros/cons of collections and the many supporting operations that go with them, Blitz should be careful about how much overhead it takes on with the base API. Java has seen a few iterations on the collections classes, trying to find the right types of balances on how to make polymorphism work for many of the interfaces and operations, how to make thread safety work, and how to make performance work, where none of the other things are required. my $0.02, in the context of game development, i would opt for simple and solid datastructures that support the fundamental CS 101 datastructures, and allow developers to add whatever sugar they might need on their own. Tony |
| ||
Hey fish, It can sometimes be useful to store the 'link' in objects if they're only ever gonna be in a single list, ala Blitz2D/3D/Plus. Type MyThing Field link:TLink Method AddToList( list:TList ) RemoveFromList 'if we were already in a list, remove us. link=list.AddLast( self ) 'track the new list we're in... End Method Method RemoveFromList() If link link.Remove ; link=Null End Method End Type Local thingList:TList=new TList Local t:MyThing=new MyThing t.AddToList thingList For thing:MyThing=EachIn thingList 'Do something with each thing Next While not quite as easy as the old system, it's potentially more flexible... you have to be careful with iterators over collections and operations that modify the backing collection. Oh yes! However, I've designed the Max lists so it's always safe to remove the 'current' object when iterating over a list with EachIn, but it still pays to be careful! |
| ||
Hey I went through everything that Fish went through, then I almost made a new topic myself (I now see there are already like 5 topics on this), but I managed to figure it out by looking through the TList code. In the end I decided to use this After function, because links were way too much of a hassle and it was messy. I don't care about the speed difference that much because my lists are small. Function After:Object(List:TList,Element:Object) Local link:TLink link=list.findlink(element) If link=Null Then RuntimeError "Object not in list" link=link.nextlink() If link=Null Then Return Null Else Return link.value() EndIf EndFunction This command should be built in and documented as a little slow in larger lists, right? Right now it seems that everyone just creates a topic on blitzbasic.com when they can't find the after command. |
| ||
Thanks Mark and Coorrae, thats very helpful. I should hold my current link in a list and use that in place of findlink.... local link:tlink = mylink.nextlink() ... get the next link then link.value() is the object? Hope I have that right? |
| ||
Oh...You obviously didn't read my previous post then! ;op |
| ||
OOOOH Thanks twoeyed :) gonna try it out. I really didn't notice it. Can I borrow one of your eyes? Thanks - going to try extending now. |
| ||
Righto, it seems to be just the ticket. I don't know how I didn't see it before. This is elegent stuff. However how do I put error checking into After and Before? I seem to be thrashing with nulls a bit. 'gather 4 points needed p2 = tPoint(p.After()) p3 = tPoint(p2.After()) p4 = tPoint(p3.After()) Seems to throw an error when I get to the end of the list. I tried going checking for null but it up ends anyway... Thank you for helping though! |
| ||
More info... The problem seems to be when I call the reverse() list method. It throws a null exception. Any idea why that could happen with your routines, TEP? |
| ||
Hmm...I obviously hadn't thought this through. ;o) This okay? |
| ||
Thanks :) Do I need to call RebuildLinks whenever I insert an item as well, as I've noticed that data gets swapped around sometimes... many thanks though :) Also, this is likely to be a lot slower on big lists isn't it? Not a problem but I need to know if thats the case... And if there is a problem when using AddAfter/Before, how do I rebuild just the links for the item I have inserted? That should give a big speed gain... |
| ||
Do I need to call RebuildLinks whenever I insert an item as well If you use the add methods, then you shouldn't need to. as I've noticed that data gets swapped around sometimes Can you post a small example?Also, this is likely to be a lot slower on big lists isn't it? Not a problem but I need to know if that's the case... |
| ||
I managed to locate the bug in my own code. Can I take this opportunity to say a big 'Thank You' as I'm using your methods now and I think it's really the best thing since sliced bread. Thanks a lot Two Eyed Pete :) |
| ||
NP, glad you found it useful...Eventually ;o) |