[17 May 2008] Advantages of using tables of functions instead of Switch statements

Contains all messages from the Hollywood mailing list between 01/2006 and 08/2012
Locked
User avatar
TheMartian
Posts: 109
Joined: Sun Feb 28, 2010 12:51 pm

[17 May 2008] Advantages of using tables of functions instead of Switch statements

Post by TheMartian »

Note: This is an archived post that was originally sent to the Hollywood mailing list on Sat, 17 May 2008 08:14:52 -0000

Finding ways to streamline your code can be rewarding in its own small way. Apart from making it look cool to others(!) and improve its readability there may be way to increase the execution speed of your code. Some time ago I wrote a mail with some examples with tricks you could use to do just that by using local variables etc. Recently I was thinking of some way to replace the structurally very nice byt also executionwise rather slow Switch statement. It turns out, that due to Hollywoods very flexible implementation of function and tables you can do just that and keep your code well structured too. Another case of something for nothing.

As an example, consider the following scenario...

You have a keyboard event handler to manage your program flow depending on which key you press. Keys are returned as values like "k" or "F1" or "LEFT" or some such string value.

Tables in Hollywood can use strings as index values. You can have a function as an element in a table. In other words, you can create a table of functions like this (The 'payload' of the functions in the example is of course rather pointless and just there for the example)

Code: Select all

MyTable = {}
Mytable["DEL"] = Function() n=n+1 EndFunction
MyTable["F1"] = Function() n=n+2 EndFunction
MyTable["LEFT"] = Function() n=n+3 EndFunction
etc.

What this means is that as an example your keyboard handler routine instead of multiple case statements in a Switch construction can look like this

Code: Select all

Function p_MyKeyboardHandler(msg)
	if StrLen(msg.key)>1	/* Then we definitely have special keys */
		dummy = MyTable[msg.key]()
	else
		/* Default key handling of regular keys like "k"  or "v" */
	endif
EndFunction
The point is not that the code is shorter. It is not, as you will still have to write a function for each key you want to handle separately from the default key response. The nice thing is that it is so much easier to structure your code for decoding (in my opinion anyway) keyboard input in this way where each odd key (like "DEL" or "F1" or "LEFT") has its own function.

As a bonus the execution time of the code is just so much faster. I tested the example seen at the end of this mail. Execution time for the code based on function calls for any key returned was 867. Execution time for the Switch construction was at best (looking for the "LEFT" string as key response) 1889 and as a worst case (looking for "DEL") 3368.

Used as here for the decoding af keyboard responses, the code is not likely to be a part of a time critical main loop, so the speed up is hardly noticable. Most of the time the main loop is just wiating for the WaitEvent to deliver a key input or some other event. But if someone finds a need for the trick inside their main loop the gain is significant.

regards Jesper

Code: Select all

@DISPLAY {color = #SILVER}

direction$ = "LEFT"
local i,dummy
local n=0

StartTimer(1)
for i=1 to 100000
Switch direction$
case "LEFT":
	n=n+1
case "RIGHT":
	n=n+1
case "UP":
	n=n+1
case "DOWN":
	n=n+1
case "TAB":
	n=n+1
case "DEL":
	n=n+1
EndSwitch
next
nprint("Test 1: ",GetTimer(1))
StopTimer(1)
nprint(n)

Action = {}
action[direction$] = Function(arg) n=n+1 EndFunction

StartTimer(1)
for i=1 to 100000
	dummy = action[direction$]()
next
nprint("Test 2: ",GetTimer(1))
StopTimer(1)
nprint(n)

waitleftmouse
end
User avatar
Clyde
Posts: 351
Joined: Sun Feb 14, 2010 12:38 pm
Location: Dresden / Germany

[19 May 2008] Re: Advantages of using tables of functions instead of Switch statements

Post by Clyde »

Note: This is an archived post that was originally sent to the Hollywood mailing list on Mon, 19 May 2008 23:12:17 +0200

Hi again,

this is quite a weird thing. :-) But also very interesting, I like it. How do you figure out such strange things? :-) Man, there are so many cool little tricks around this mailing list, but it is so unstructured. :-/ It would be cool to have a little website that covers all these tricks and make them better "ready to be found". Hm, after this uni term I will think further about this. I have 2.5 month of summer holidays, so besides my other projects there should be time for this. And help would be appreciated. ;-)

Concerning your little programme, Jesper, at the end of your mail: The execution time are always nearly the same for switch and table magic. Did I miss sth??? :-(

Greetings Micha
Currently using: Hollywood 9 with Windows IDE and Hollywood 9 with Visual Studio Code and hw4vsc
User avatar
TheMartian
Posts: 109
Joined: Sun Feb 28, 2010 12:51 pm

[20 May 2008] Re: Advantages of using tables of functions instead of Switch statements

Post by TheMartian »

Note: This is an archived post that was originally sent to the Hollywood mailing list on Tue, 20 May 2008 19:55:17 -0000

Hmm - With a single case statement inside the Switch it seems to clock in at around 1500 whereas the function call executes at around 850 for me. Each added case adds about 200-400 to the time. Strangely it is not quite a linear growth but wobbles a bit. So it sounds odd that they should clock at about the same when you try. I use an A1 XE G4 for my programming. I haven't tried on the old A4000 though.

I get these ideas about alternative ways of coding because I have been working with quite a lot of different languages including such oddities (by todays standards) as Cobol, APL, Forth, Modula, Delphi, VB and a zillion versions of basic specific to old 8 bit computers. Mostly just for fun as with Hollywood today. In the early eighties you could often get your interpreted programs to run much faster by such tricks and as a dealer in home computers in that 'golden age' of do it yourself home computers I had an opportunity to try just about all the odd machines that appeared then. I still have an Enterprise 128 lurking in a cabinet and some old commodore stuff apart from my Amigas though it only gets aired every few years :-)

PS. I think a logical extension of this idea of using a function call is to make a construction like: (Just tried a very simple example as below which works ok)

Code: Select all

Const #BUTTON = -1
action = {}
action[#BUTTON] = {}
action[#BUTTON]["F1"] = Function() n=1 Return(n) EndFunction
action[#BUTTON]["F2"] = Function() n=2 Return(n) EndFunction
action[#CHECKBOX]["F1"] = Function() n=3 Return(n) EndFunction
action[#CHECKBOX]["F2"] = Function() n=4 Return(n) EndFunction
Then the actual code in the main program to execute any of the functions would be something like:

Code: Select all

arg1 = #BUTTON
arg2$ = "F1"

nprint(action[arg1][arg2$]())
So no multilevel Switch statements on several pages of code, and all functions could be grouped together in the code to help readability.

The only problem I know of so far is how to implement a default function like you have a Default: in a Switch statement to catch an argument with no matching index. I guess I could wrap the function call in a

Code: Select all

ExitOnError(False)
nprint(action[arg1][arg2$]())
/* do a check on error code */
ExitOnError(True)
/* continue program */
construction. I have not tested it though.

regards Jesper
Locked