Ok… what you have are “heavy” pieces that are being intantiated, do their job, and then get destroyed.
See if you can figure out a way to instantiate them ONCE, at the beginning of the game, located at a designated holding box at some off-board location; when needed, they get moved into the hex of interest, do their thing, and then move back to the holding box , until needed again
Remember, we are talking in the context of BeanShell here - not general programming - in which case as switch statement would probably be better. Remember how the BeanShell expressions in Vassal are evaluated. I’m not sure you can actually do a switch - haven’t tried though - maybe
{
ret = 10;
switch(number) {
case 1: ret = 1; break;
case 2: ret = 2; break;
...
}
ret
}
would work. So I don’t think we’re wrong. Also, the question is how fast the interpreter does a row of ternary expression compared to a switch - they are probably comparable - both O(N).
I’m not sure why you bring up Rust in this discussion. While I agree with a lot of your sentiments about Rust, I think your comments are beside the point.
Speaking of bad practises! Sure, if you are coding ASM - fine - but that is certainly not the case in point. C has longjmp but that could easily generate a whole slew of problems unless one is not very careful, and most compilers will optimise a switch to something like a computed GOTO. I believe Java does not have a GOTO statement. Personally, I prefer INTERCAL’s COME FROM statement
And then …
Begin rant
To me, Rust seems like a fad. Sure, it addresses some issues that are legitimate, but I believe at a high cost (over-design). Indeed, some C++ standard committee members have expressed concerns about memory safety, but want to work within the current C/C++ framework.
There have been many other fads in the programming language sphere in the past, such as Go, C#, Ruby, and even Java. Before that, there was Ada, Delphi, SmallTalk, and INTERCAL. Very few languages have stood the test of time, and C/C++ has certainly persevered. Python seems like another candidate for perpetuity. But - I might be biased
That said, it seems like Vassal 4 will be written in Rust, which brings up questions of scripting and introspection End rant
{
ret = 10;
switch(number) {
case 1: ret = 1; break;
case 2: ret = 2; break;
...
}
ret
}
would work in the Vassal interpreter?
While measuring is a good idea, it may not be that simple to do with Vassal BeanShell scripts. Also, it is not clear that there would be a noticeable difference, because the set-up and tear-down time might swamp the total time used to interpret the BeanShell code.
I put the following code into ternaryVsSwitch.bsh
import java.util.stream.IntStream;
public class StopWatch {
long total = 0;
long laps = 0;
long start = 0;
public StopWatch() {}
protected long tick() {
return System.currentTimeMillis();
}
public void start() {
start = tick();
}
public void lap() {
total += tick() - start;
laps += 1;
}
public long total() {
return total;
}
public float mean() {
return (float)total / laps;
}
public long n() {
return laps;
}
};
public class Test {
protected String name;
protected int[] ints;
public Test(String nme, int[] data) {
name = nme;
ints = data;
}
public abstract void test(int i);
public void run() {
StopWatch sw = new StopWatch();
for (int i : ints) {
sw.start();
test(i);
sw.lap();
}
print(name + " " + sw.n() + " calls over " + sw.total() + " ms "
+ sw.mean() + " ms average");
}
}
public class TestSwitch extends Test
{
public TestSwitch(int[] data) {
super("Switch",data);
}
public void test(int i) {
int foo = 0;
switch (i) {
case 1:
foo = 10;
break;
case 2:
foo = 20;
break;
case 3:
foo = 30;
break;
case 4:
foo = 40;
break;
case 5:
foo = 50;
break;
default:
foo = 60;
break;
}
}
};
public class TestTernary extends Test
{
public TestTernary(int[] data) {
super("Ternary",data);
}
public void test(int i) {
int foo = (i == 1 ? 10 :
i == 2 ? 20 :
i == 3 ? 30 :
i == 4 ? 40 :
i == 5 ? 50 : 60);
}
};
Random ran = new Random();
IntStream ints = ran.ints(10000,1,7);
int[] data = ints.toArray();
TestSwitch t1 = new TestSwitch(data);
TestTernary t2 = new TestTernary(data);
t1.run();
t2.run();
and then I run it as
$ bsh ternaryVsSwitch.bsh
and I consistently get that which ever test I put first, is faster:
$ bsh ternaryVsSwitch.bsh
Switch 10000 calls over 879 ms 0.0879 ms average
Ternary 10000 calls over 801 ms 0.0801 ms average
Change order
$ bsh ternaryVsSwitch.bsh
Ternary 10000 calls over 919 ms 0.0919 ms average
Switch 10000 calls over 833 ms 0.0833 ms average
from which we can probably conclude that the two solutions are comparable in execution speed.
Doing the same test - though with slightly modified source code - in compiled java code yields a similar result.