Right now, I find the current if $choice==0 .... elif $choice==1 .... code block seem to be start slowing down when there’s a lot of blocks. I’m wondering if there can be something like keywords switchif,otherwise,endswitch which does that codeblock. Something that skip the $1==v calculation. Like an advanced arg control block which actually allows you to execute multiple commands at once at a switch case.
For example:
if $1==0 do_something_a
elif $1==1 do_something_b
elif $1==2 do_something_c
...
fi
If $1 is equal to 5, it will go directly to the fifth otherwise and execute commands within it, and ignores all the calculation for elseif. Or maybe the keyword should just be switch_case,case,done.
That would look like:
switchcase $1
case do_something_a
case do_something_b
done
Also, I would like a better way of doing a0.....a1000={expr('x',1000)}, and the numbers don’t have to be numbers. I tried with image, then crop(#-1), but it seems a little slow. expr is single-threaded?
Finally, arg in math parser seem to execute everything inside it, then pick the result. I don’t like that behavior myself, can there be improvement here? The expected result is that it only execute one.
Switch would make the code neater. You are missing the case item value that the variable must match and the optional default command when no conditions are met. I suppose a break for each case could be implied.
switch variable
case item command
case item command
default command
done
Bonus for fun, since fi is the counterpart of if, make it hctiws for switch.
Edit: Or bign.
@David_Tschumperlefi no longer is a shortcut, but in the reference document, fi refers to itself as a shortcut. @grosgood’s tutorial refers to endif, which no longer exists.
On the subject of switch, what if there are two conditions that should be factored into as a single case? I guess a comma as a separator would be possible, but at that point, it’s probably harder to do. So, if variable is equal to 10 and one of the case is aurora,10 then execute case aurora,10 basically.
Yes. Or I want a switch case where no item is needed and implied number. Maybe two different version of switch. One would be switch like you suggested, and the other is switch_number which ignores evaluating conditions and is inherently faster in theory (case without items).
item can be any alphanumeric value in switch statements. At least, that is the expectation of switch from other languages. I understand the desire to truncate it like foreach…done does for repeat…local…donedone.
It also would be nice to eliminate the need to do ‘$var’==’$string’ in case of string-based condition.
If you look at pal command, you’d note a lot of +_pal_{short_name_of_pal}, and I’m trying to remove those to a single command. It’s possible, but all solution has some drawbacks while the current version is fast as possible.
If you’re using a lot of if ... elif inside a performance critical section, that’s usually a sign that there’s a more efficient way of doing it (using arrays, maps, different algo entirely).
If you’re going beyond 3 or 4, perhaps consider arg or arg0 - you can assign a variable with a command to execute. Switch statement is a last resort for me in most languages, I only use it if I’m coding quickly/lazily with intent to fix later.
I do agree with that, and usually there is a option. However, I point out that I have many subcommands under pal command.That’s a bad thing because more subcommands means G’MIC gets slower from what I have read here, and I wish to have a solution here.
There is no O(1) solution to removing subcommands and keep the time. If/elif/else is O(n), and arg can’t accept multiple command under it. Theoretically, a switch code block for many subcommands instead would solve this. I tested with several Python script to generate G’MIC codes.
You can at the very least create a solution with the same asymptotic performance as g’mic itself, by implementing the same method it uses but in interpreted code. Yes, there’s an overhead.
Another option is to put the definitions of those command inside another (using command). Then you need only “warm it up” when you intend to use them. I also have to wonder - is the perf really that critical? Are you creating new palettes inside a loop or something?
My thoughts on this switch() ... case A : ... case B : ... structure :
Personally , I don’t think this is really more readable that using if... elif... else... fi . Particularly if you have a lot of case or if each case is followed by a large code block.
In C/C++, I see the advantage of using the switch() syntax: sometimes, the compiler is able to optimize greatly the corresponding code compared to a corresponding use of if... else if... else . I’ve already tried to read the generated ASM code for this kind of switch() construct and I was surprised to see that the compiler had generated an array of pointers to functions, because the number of case was limited, and the range of compared values were like int in [0,10].
But for a purely interpreted language, having a switch statement seems useless, as you won’t get compiler tricks as you can get with C/C++.
As @garagecoder said, if you want to optimize the expression (as the C/C++ compiler does), then try to explicitly use arrays or named function (with a suffix that is the value of the tested condition).
Something like:
foo :
m "case_0 : echo \"0\""
m "case_1 : echo \"1\""
m "case_2 : echo \"2\""
case_$1
um case0,case1,case2
As @Reptorian said, what costs a bit is testing the condition $1==value , for each if. But, this suggests to optimize the evaluation of the condition, rather than introducing a new switch control. I’ll try to see what I can do for quickly testing value1==value2 and value1!=value2, I guess this is something doable (there are already a few simple math expressions that are optimized and that do not require a call to the math parser).
I found that accessing commands does have an annoying delay — how much slower or faster than our other options, I am not certain. For strings, I am in habit of using arg or arg0. I typically have the command do all the decision-making processing before the rest of the code. In my mind, that makes the code more readable and may reduce the structural complexity.
I agree with David that optimizing conditional processing would make things better.
I think I’ll wait for the optimization, but right now, +pal is fine in context of speed and I do prefer to remove subcommands to a single command which is where the problems lies in. Unless hopefully, I’m missing something about too much subcommands slowing down G’MIC (I know that would take a lot more). @KaRo did talked about many subcommands before in my G’MIC thread.
All ideas I tried:
Storing pal subcommands into b64 codes - Problem: Loading the image from the base64 code takes up most time. Slower than current code. And using p_subcommand variables with numbers next to it to acts as key for each pals.
m subcommands. - Problem it seems that the importing subcommands slows it down.
Storing pal subcommands into if elif blocks. - Seems fine mostly, however, it’s slower than the current implementation as the farther you stray from 0, the slower it is. If that wasn’t a issue, I’d pick this solution. I have not tried using ‘$var’==’$str’, but used number-based condition instead.
OK, but it would help to have an actual target; just because something is a bit slower doesn’t always mean it’s bad or useless. If you have a specific example where it makes something take several seconds more, then it gives us something to aim for and test against!
Optimization works in case of number. But from what I see, optimization doesn’t work in case of this:
if '$string'=='$str0' command_0
elif '$string'=='$str1' command_1
....
elif '$string'=='$str399' command_399
else command_default
fi
I believe it is because it always evaluate ‘$string’. Maybe switch would help in this case because you only need ‘$string’ and the switch control would keep ‘$string’ instead of evaluating it over and over again.
As for @garagecoder: There is no case I found that takes over a second or more. But, the longest case would be using merge command. In the case of pal, here’s the code - G'MIC Pal Command Modified - Pastebin.com .
Using tic toc, pal_new is 10 times slower than current implementation which runs .003 s or less for two palettes. I’d imagine it get really slower if you load many palettes at once. Even base642img has this issue.