• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Is 'this' possible?

Status
Not open for further replies.
Level 12
Joined
Jan 2, 2016
Messages
973
I want to make something like this:
Code:
function Func1 takes.......
........
function Func2 takes.......
........
function Func3 .........
........
and so on, and I want to call these functions like this:
Code:
call Func(I2S(i))()

Or something similar...

I kind a don't wanna do:
Code:
if i == 1 then
    call Func1()
elseif i == 2 then
    call Func2()
elseif .............
 
Level 12
Joined
Jan 2, 2016
Messages
973
so it would look like call ExecuteFunc("Func"+I2S(i))?

if that will work, what is faster? having 10 x if checks like
Code:
if i == 1 then
    call Func1()
elseif i == 2 then
    call Func2()
elseif i == 3 then
    call Func3()
elseif i == 4 then
    call Func4()
elseif i == 5 then .....

or the ExecuteFunc?
(processing wise, not writing wise, cuz that is obvious :D)
 
Level 12
Joined
May 22, 2015
Messages
1,051
You can do it with an array of triggers. Then you do call TriggerEvaluate(udg_triggerFunc[i]). Though it is notable that you'd then have to create a bunch of triggers (with no events, but more triggers might cost you somewhere else).

It is supposedly faster than ExecuteFunc(...) according to this: http://www.hiveworkshop.com/forums/lab-715/jass-benchmarking-results-245362/

However, you can see that it is significantly faster to do a regular function call. If it's that bad, use ExecuteFunc, since you don't need to set up all the triggers that way, but using if/elseif/else will be the most efficient.
 
Level 17
Joined
Dec 11, 2014
Messages
2,004
In that case, I'm bad at Jass after all! :D (Though I'm used Jass a little in every of my creation but still bad at it..)

Btw, let's go back to the main topic.

If you say something incorrect, don't say "I'm horrible" or stuff like that. Everybody makes mistakes.

Performance-wiser and Better control option are the If/Then/Elses. Also for making the JASS code smaller you can use a texmacro and a loop in it -or maybe a loop and a textmacro in it- (in case you know vJASS).
 
Level 14
Joined
Nov 30, 2013
Messages
926
If you say something incorrect, don't say "I'm horrible" or stuff like that. Everybody makes mistakes.

Performance-wiser and Better control option are the If/Then/Elses. Also for making the JASS code smaller you can use a texmacro and a loop in it -or maybe a loop and a textmacro in it- (in case you know vJASS).

On the second thought, I actually kinda experience Jass a little except for vJass because I don't do spell triggers alot.
I don't know if JassCraft is able to do vJass stuff but nevermind.

Thanks for pointing that out.
 
Level 12
Joined
May 22, 2015
Messages
1,051
this brings us to question, how many if conditions would you have to evaluate for it to be slower than ExecuteFunc :D

Ya, that's tough to answer. Also, does ExecuteFunc get more expensive as you add more functions to your map? I heard some theories that it does a linear search trying to match the given string with the function name. It explains why longer function names would take longer to do with ExecuteFunc.

The trigger way is the best for making it O(1) lookup speed. Though, as I mentioned, there could be some cost for having a whole bunch of triggers.

It would be best if one function could figure out what to do in O(1) time, if possible.

EDIT:
Just had the idea that you could set this up like a binary tree of if statements (assuming it is integers that determine the function to use). You could figure out which function to run in log(N) time which will probably make it always faster unless you're doing something completely insane.
 
Last edited:
Level 12
Joined
Jan 2, 2016
Messages
973
this brings us to question, how many if conditions would you have to evaluate for it to be slower than ExecuteFunc :D

Yeah, I'm wondering that too, but well, now I'm wondering something else, tho it's kind a similar to the original question:

Is it possible to do this without an array:
JASS:
local unit uA = //some unit
local unit uB = //another unit
local unit uC = //some other unit
...
local integer i = 1
loop
     exitwhen i > 26
     call PauseUnit( u(I2L(i)), true)  //I2L would be a custom function, that takes integer and returns letter
     set i = i + 1
endloop
I know I can do this with arrays, but I just wanna know if this is possible in jass xP
Said in other words, I'm wondering if there is some kind of function, that takes string and returns a variable('s name/adress ~not sure how it's called~)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
I know I can do this with arrays, but I just wanna know if this is possible in jass xP
Said in other words, I'm wondering if there is some kind of function, that takes string and returns a variable('s name/adress ~not sure how it's called~)
There are no natives to enumerate what elements exist in the JASS script. There is also no sensible use case for such functionality. Let us not even get on to the safety issues it raises.

Why do you need this functionality? I am pretty sure that there is a better solution to whatever you are trying to do that does not need this functionality.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
If there was such function - it could've made some triggers quite shorter, and more functional.
One might think that, but in the end it would likely reduce the coding quality by reducing maintainability and making it less efficient.

Maintainability is reduced because variable references no longer depend just on direct named references, but also on some arbitrarily constructed ones. A name might be refactored during maintenance as part of a code cleanup but these constructed references are not caught. The result is an error during gameplay that may be hard to detect.

Performance is reduced as you are now using dynamic lookup at run time rather than static linking with computed offsets. That said this slow lookup time makes no difference in JASS as JASS already does this with named elements, hence why it is so slow. In reality an implementation would mean 1+ more function calls though which would slow execution down a bit due to the 1+ more name lookups required.
 
Level 12
Joined
Jan 2, 2016
Messages
973
Hmm, back to the oridinal question.
I found something interesting about vJASS called "textmacros"
JASS:
    //! textmacro Increase takes TYPEWORD
    function IncreaseStored$TYPEWORD$ takes gamecache g, string m, string l returns nothing
        call Store$TYPEWORD$(g,m,l,GetStored$TYPEWORD$(g,m,l)+1)
    endfunction
    //! endtextmacro

    //! runtextmacro Increase("Integer")
    //! runtextmacro Increase("Real")
I suppose it's possible to make the function a textmacro:
JASS:
//! textmacro FuncNr takes NUMBER
function ExecuteTheRightFunction takes nothing returns nothing
    call Func$NUMBER$()
endfunction
//! endtextmacro

//! runtextmacro FuncNr(I2S(i))
what do you think?
 
Level 12
Joined
Jan 2, 2016
Messages
973
Well, that's GOOD to know ^_^
I will likely start using vJASS soon :)
However, can you explain a bit. Do I need to put the textmacro in a library?
And how would my trigger look like then?
Will it be something like this:
JASS:
library FuncNrLib
    //! textmacro FuncNr takes NUMBER
    function ExecuteTheRightFunction takes nothing returns nothing
        call Func$NUMBER$()
    endfunction
    //! endtextmacro
endlibrary

function Func1 takes nothing returns nothing
// stuff
endfunction

function Func2 takes nothing returns nothing
// other stuff
endfunction

function Func3 takes nothing returns nothing
// more stuff
endfunction

function MainFunc takes nothing returns nothing
    local integer i = RandomInt(1,3)
    //! runtextmacro FuncNr(I2S(i))
endfunction
 

EdgeOfChaos

E

EdgeOfChaos

Why not just use ExecuteFunc
Something like this should work: call ExecuteFunc("myMethod"+I2S(i))
Who cares about slightly higher time to call? So it might take 0.08ms instead of 0.07ms to call the function. It doesn't matter unless you're doing this every 0.01 seconds or something, and this code is a lot shorter when compared to that textmacro stuff.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Something like this should work: call ExecuteFunc("myMethod"+I2S(i))
Who cares about slightly higher time to call? So it might take 0.08ms instead of 0.07ms to call the function. It doesn't matter unless you're doing this every 0.01 seconds or something, and this code is a lot shorter when compared to that textmacro stuff.
The problem is not so much the execution time, it is that programmatically what you are doing is bad. It may seem like a good idea, but you are opening the script to maintainability and readability issues.

For example, tools like vexorian's optimizer might break the script because the function is not statically linked. I tries its best not to break such dynamic calls when obfuscating but some times it will still break them.
 
Status
Not open for further replies.
Top