| 07-15-2006, 03:54 AM | #1 |
With all the talk of extending and object orienting the JASS, I thought I'd give just one example of what my JassPreProcessor currently does. Take a look at this interesting line of code: JASS:call ForGroup(selected_targets, jpp_callback ABIL_EmeraldSpiritsTargetEnum(source, actual_damage)) It does something that is not possible in JASS, that is it calls a function with arguments for each unit in a group. Normally, this would read: JASS:
set SomeGlobalVar = source
set SomeOtherGlobal = actual_damage
call ForGroup(selected_targets, function ABIL_EmeraldSpiritsTargetEnum)
As most Jassers are aware of, callback functions such as the one ForGroup take no arguments meaning arguments must be passed by global variables (or *shudder* gamecache). This is very inconvenient and extremely bad programming practice. So, one of the new features of my JPP (jass preprocessor) is to turn: JASS:jpp_callback ABIL_EmeraldSpiritsTargetEnum takes unit source, integer damage returns nothing call DebugMsg(GetUnitName(source) + " damages " + GetUnitName(GetEnumUnit()) + ", Damage = " + I2S(damage)) endfunction function ABIL_EmeraldSpirits takes group targets returns nothing call ForGroup(targets, jpp_callback ABIL_EmeraldSpiritsTargetEnum(source, actual_damage)) endfunction automatically into this in the war3map.j: JASS:function ABIL_EmeraldSpiritsTargetEnum takes nothing returns nothing local unit source = jpp_cb0 local integer damage = jpp_cb1 call DebugMsg(GetUnitName(source) + " damages " + GetUnitName(GetEnumUnit()) + ", Damage = " + I2S(damage)) endfunction function ABIL_EmeraldSpirits takes group targets returns nothing set jpp_cb0 = source set jpp_cb1 = actual_damage call ForGroup(selected_targets, function ABIL_EmeraldSpiritsTargetEnum) endfunction It will of course declare globals of correct types and insert it into the globals section of war3map.j. Simple and Effective! |
| 07-15-2006, 04:03 AM | #2 |
Good job. "This is very inconvenient and extremely bad programming practice." is a little dramatic. |
| 07-15-2006, 04:33 AM | #3 | |
Quote:
Well, it may not be very inconvenient. Of course, setting some global variables before calling a callback is only a line or two. But it IS extremely bad programming practice, that's for sure :) |
| 07-15-2006, 04:38 AM | #4 |
For group global less JASS:loop set GFilter = FirstOfGroup(ToDamage) exitwhen GFilter == null call GroupRemoveUnit(ToDamage,GFilter) if not IsUnitInGroup(GFilter,Group) and IsUnitEnemy(GFilter,GetOwningPlayer(Caster)) then call UnitDamageTarget(Caster,GFilter,Damage,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS) call GroupAddUnit(Group,GFilter) endif endloop It used for wave damaging and will damage unit only a time Your "code" is useless |
| 07-15-2006, 04:40 AM | #5 |
Not when callback functions are used in more places than just at for groups. |
| 07-15-2006, 05:11 AM | #6 |
Pontificate, v. 1. To express opinions or judgments in a dogmatic way. 2. Beg to be moderated with reckless abandon |
| 07-15-2006, 06:49 AM | #7 | |
Quote:
If you do not see its immense usefullness I can't help you :) Btw, PipeDream, care to explain the meaning of your last post to those of us, including me, who just don't understand what on earth it is you are saying? |
| 07-15-2006, 07:53 AM | #8 |
Seems ok, you should tell Vex about your precompiler, he's been meaning to do the same in his set JASS=JASS+1 thread |
| 07-15-2006, 02:39 PM | #9 | |
Quote:
I think it was addressed to DioD in a "keep your mouth shut" way. Or so I say. |
| 07-15-2006, 03:55 PM | #10 | ||
hmn diod, yes but no. That works, but is slower than a for group and it gets rid of the group, so if you want to keep the group after the iteration, you have to either clone the group before doing so or keep adding units to another group and work arounds like that. jpp_callback seems like bad syntax. Quote:
Why should it be a bad programming practice? Quote:
|
| 07-15-2006, 04:01 PM | #11 | |
Quote:
Hard to remember I say, if you find the function keyword and then the function name is followed by the ( operator then it is easy to identify a callback |
| 07-15-2006, 06:27 PM | #12 |
First, jpp_callback does not work just for ForGroup. It works for every callback and can be used in any imaginable circumstance where one normally would set global variables. As for syntax, I could make the callback function use the normal function signature, process every callback call and then seek out the functions that are being used as callbacks and modify them like you suggest. I chose jpp_callback as a special keyword because I want to make it as obvious as possible that something different is going on. Magic preprocessing should be clearly visible in the sourcecode. As for why it is bad programming practice to set some global variables and then call a function that read those variables vs passing those same variables through the normal function calling syntax consists of several reasons: It makes the syntax less complex making it easier to use, read and maintain, it removes the need to manage a large amount of global variables and concentrates all the "extra work" needed get arguments into callbacks into one single line. |
| 07-15-2006, 08:23 PM | #13 | ||
I can't think on callbacks that would use more than 3 variables, and for them I could use bj variables, they are always there. But well it is an annoyance and it is unconfortable but not a bad programming practice. Quote:
-- Quote:
And that is ForGroup and ForForce, but ForForce is like incredibly useless anyways. |
| 07-15-2006, 09:02 PM | #14 |
What about timers, trigger conditions, etc? Unless those aren't callbacks... |
| 07-15-2006, 09:04 PM | #15 |
How exactly would you apply global variables there? |
