| 07-05-2008, 12:33 AM | #1 |
I have a problem right now, first of all, I wish to move from completely wrong CSCache to "Table" There's a little problem with that and it is that I still need to use H2I , I think H2I increases uglyness of code by 20%, I also think it would look harder for other people, it is actually quite lame. If you want your map to be sane, it is not good to use more than a gamecache library, gamecache files are very expensive if you ask, specially with that risk associated to them of making things stop working in single player, two independent libraries can't use the same gamecache file, if they figured a way to avoid collissions they would still be unable to deal with the required flushing at init. There's also the small problem that if I let Table as it is right now, the number of scattered H2I functions will mutliply, I personally think I need H2I integrated to Table somehow, because of the scattered H2I risk I just mentioned and the unfriendliness I mentioned in the other paragraph. I had a dream after all the discussion about the definition of associative arrays with Cohadar. What if I could actually make Tables be associative arrays even for that definition in which keys are not integers!. In fact, even similar to dynamic languages' associative arrays. JASS://The ideal: function test takes nothing returns nothing local Table t=Table.create() set t["oranges"]=12 set t["apples"]=2 set t["bananas"]=t["apples"]*2 set t[34]=t[1923777]+t[-1283] set t[ GetTriggerUnit() ] = t[GetTriggerUnit() ] +1 The problem is that the ideal is impossible to make in vJass, I know I control vJass and I could actually make it so function overloading worked , but then it is not something I really want, the second option would be to allow type specialization for functions/methods, this is a nice idea that unfortunately I cannot add without a lot of effort I am not willing to use yet. So, the closest I got to the ideal was this: Possible new Table version:library Table initializer init //*************************************************************** //* Table object //* ------------ //* //* set t=Table.create() - instanceates a new table object //* call t.destroy() - destroys it //* t[1234567] - Get value for key 1234567 //* (zero if not assigned previously) //* set t[12341]=32 - Assigning it. //* call t.flush(12341) - Flushes the stored value, so it //* doesn't use any more memory //* t.exists(32) - Was key 32 assigned? Notice //* that flush() unassigns values. //* call t.reset() - Flushes the whole contents of the //* Table. //* //* call t.destroy() - Does reset() and also recycles the id. //* //*************************************************************** //============================================================= globals private constant integer MAX_INSTANCES=400000 //========================================================= private gamecache gc endglobals private keyword HTable private keyword STable struct Table[MAX_INSTANCES] method operator [] takes integer key returns integer return GetStoredInteger(gc,I2S(this),I2S(key)) endmethod method operator []= takes integer key, integer value returns nothing call StoreInteger(gc,I2S(this),I2S(key), value) endmethod method flush takes integer key returns nothing call FlushStoredInteger(gc,I2S(this),I2S(key)) endmethod method reset takes nothing returns nothing call FlushStoredMission(gc,I2S(this)) endmethod method exists takes integer key returns boolean return HaveStoredInteger(gc,I2S(this),I2S(key)) endmethod private method onDestroy takes nothing returns nothing call FlushStoredMission(gc,I2S(this)) endmethod method operator handle takes nothing returns HTable return HTable(this) endmethod method operator string takes nothing returns STable return STable(this) endmethod method operator integer takes nothing returns Table return Table(this) endmethod endstruct private function H2I takes handle h returns integer return h return 0 endfunction private struct HTable method operator [] takes handle key returns integer return GetStoredInteger(gc,I2S(this),I2S(H2I(key))) endmethod method operator []= takes handle key, integer value returns nothing call StoreInteger(gc,I2S(this),I2S(H2I(key)), value) endmethod method flush takes handle key returns nothing call FlushStoredInteger(gc,I2S(this),I2S(H2I(key))) endmethod method exists takes handle key returns boolean return HaveStoredInteger(gc,I2S(this),I2S(H2I(key))) endmethod endstruct private struct STable method operator [] takes string key returns integer return GetStoredInteger(gc,I2S(this),key) endmethod method operator []= takes string key, integer value returns nothing call StoreInteger(gc,I2S(this),key, value) endmethod method flush takes string key returns nothing call FlushStoredInteger(gc,I2S(this),key) endmethod method exists takes string key returns boolean return HaveStoredInteger(gc,I2S(this),key) endmethod endstruct private function init takes nothing returns nothing call FlushGameCache(InitGameCache("libtable.gc")) set gc=InitGameCache("libtable.gc") endfunction endlibrary So the code that worked with the "ideal" will look like this: [/hiddenjass] JASS://The ugly reality function test takes nothing returns nothing local Table t=Table.create() set t.string["oranges"]=12 set t.string["apples"]=2 set t.string["bananas"]=t.string["apples"]*2 set t[34]=t[1923777]+t.integer[-1283] //for consistency I guess set t.handle[ GetTriggerUnit() ] = t.handle[GetTriggerUnit() ] +1 So, my conclusions:
Question, how does the "ugly reality" code look? My excuse would be "Until vJass' compiler gets smarter you need to specify what type to use for the key, (unless it is integer) " But I think the logic is backwards there? Edit: Thanks to the Jass tag "ugly reality" does not look as shocking as when I look at it in gVim, a screenshot: Edit II: Ah, this is how it compiles: JASS:function test takes nothing returns nothing local integer t=s__Table__allocate() call StoreInteger(Table__gc , I2S((((t)))) , ("oranges") , ( 12)) // INLINED!! call StoreInteger(Table__gc , I2S((((t)))) , ("apples") , ( 2)) // INLINED!! call StoreInteger(Table__gc , I2S((((t)))) , ("bananas") , ( (GetStoredInteger(Table__gc , I2S((((t)))) , ("apples"))) * 2)) // INLINED!! call StoreInteger(Table__gc , I2S((t)) , I2S((34)) , ( (GetStoredInteger(Table__gc , I2S((t)) , I2S((1923777)))) + (GetStoredInteger(Table__gc , I2S((((t)))) , I2S((- 1283)))))) //for consistency I guess // INLINED!! call StoreInteger(Table__gc , I2S((((t)))) , I2S(Table__H2I((GetTriggerUnit()))) , ( (GetStoredInteger(Table__gc , I2S((((t)))) , I2S(Table__H2I((GetTriggerUnit()))))) + 1)) // INLINED!! endfunction |
| 07-05-2008, 01:07 AM | #2 |
I'm really having trouble understanding how those new method operators are understood by the compiler. What are they normaly used for? This really is some heavy abuse, I'd almost say I'd rather just use H2I myself and get the same functionality while having more understanding of what it is that I'm doing but the point is that it's not the same functionality, since this also allows the use of strings. I'm looking forward to a more detailed explanation of why it works. Edit: nevermind, I figured out the logic behind it, it's actually just simple typecasting. Since when do we have type operators (int, string, handle)? Is this something invented specifically to support this abuse or was this feature implemented before and if so for what application? Also, does this not generate any error messages in debug mode? I'd think there should be an error message if you try to do stuff with an uninitialised struct instance. |
| 07-05-2008, 01:59 AM | #3 | |
Nah, debug mode does not babysit against using unitialized struct ids. Dunno if it would ever do. Quote:
Yeah, it is crazy. |
| 07-05-2008, 05:26 AM | #4 |
You could make function overloading? Fuck man, PLEASE, I BEG YOU, PLEASE ADD IT TO YOUR LIST OF THINGS TO DO. |
| 07-05-2008, 11:18 AM | #5 | |
Quote:
JASS:globals private Table tI private HandleTable tH private StringTable tS endglobals private function init takes nothing returns nothing set tI=Table.create() set tH=HandleTable(tI) set tS=StringTable(tI) endfunction Edit: I know I can get around this by using structs, but it would still be nice if we had a more direct way of storing strings and reals to GC, other than using the natives directly of course. |
| 07-05-2008, 03:41 PM | #6 | |
JASS:local Table t=Table.create() set HTable(t)[ GetTriggerUnit() ] = 2 It is perfectly possible. (Though it is still evil abuse) edit: Quote:
|
| 07-05-2008, 03:52 PM | #7 |
JASS:struct StringTable extends Table struct UnitTable extends Table //.... |
| 07-05-2008, 04:15 PM | #8 |
Can't replace methods in childs. |
| 07-05-2008, 08:05 PM | #9 | |
Quote:
|
| 07-05-2008, 09:05 PM | #10 |
are we talking about the same possible conflict? |
| 07-06-2008, 12:57 AM | #11 |
I mean set tab[i]=x vs set HandleTable(tab)[u]=y in cases when i happens to equal H2I(u). |
