fbpx
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1
  • 2

TOPIC: Switch vs do case

Switch vs do case 1 year 6 months ago #1

Hi

I found this example for X# and was shocked, do my VO always check every CASE ? i was testing it and VO is leaving the DO CASE when one is matching .
so, is there realy a different ?? or do i dont understand this X# example ?

// The SWITCH statement is a replacement for the DO CASE statement
// The biggest difference is that the expression (in this case sDeveloper) is only evaluated once.
// which will have a performance benefit over the DO CASE statement
//
using System.Collections.Generic

Function Start() as void
FOREACH VAR sDeveloper in GetDevelopers()
SWITCH sDeveloper:ToUpper()
CASE "FABRICE"
? sDeveloper, "France"
CASE "CHRIS"
CASE "NIKOS"
? sDeveloper, "Greece"
CASE "ROBERT"
? sDeveloper, "The Netherlands"
OTHERWISE
? sDeveloper, "Earth"
END SWITCH
NEXT
Console.ReadKey()
RETURN

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #2

Hi Horst,

yes, VO was leaving when a match was found. But if you have a thousend CASE's und the last one matches, it did 999 comparisons/test first. The same with X# of course. In the case of sDeveloper:ToUpper() it will execute this method call 999! times for nothing.

SWITCH does one test and then knows what to do.

But switch does more: it checks at compile time if there are to identical conditions. This is valid code:

DO CASE
CASE var == "a"
DoSomething()
CASE var == "b"
.
.
.
CASE var == "a"
DoAnotherThing()
OTHERWISE
NOP
END CASE

In complex scenarios you might wonder, why DoAnotherThing() never executes.

This is not valid code:

SWITCH var
CASE "a"
DoSomething()
CASE "b"
.
.
.
CASE "a"
DoAnotherThing()
OTHERWISE
NOP
END SWITCH

will generate a compile time error at the last CASE because of identical matches.

Saying that using SWITCH makes your code faster and more error proof.

Frank

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #3

  • wriedmann
  • wriedmann's Avatar
  • Offline
  • Posts: 1426
  • Karma: 6
Hi Horst,

the switch and the do case statement are two completely different beasts.

As Frank wrote, the switch statement is faster and less error prone, but the do case is much, much more flexible.

I can replace only a small fraction of my do case blocks with switch blocks, so both have the right to exist.

The VO help says about the do case:

If this expression evaluates to TRUE, the statements following it up until the next CASE, OTHERWISE, or ENDCASE are executed. Afterwards, control branches to the statement following the next ENDCASE statement

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #4

Guys,

The way DO CASE is implemented in VO (and x# and vulcan for compatibility), it is just a more fancy alternative to IF..ELSEIF. This code in VO

IF something == 1
...
ELSEIF something == 2
...
ELSEIF something == 3
...
ELSE
...
ENDIF

is identical to

DO CASE
CASE something == 1
..
CASE something == 2
..
CASE something == 3
..
OTHERWISE
...
END CASE

Having said that, I personally prefer the DO CASE syntax, which I think makes the code easier to read so I prefer using it to IF..ELSEIF.

But yes, SWITCH is a very different thing, much more efficient but cannot always be used as a replacement for DO CASE.

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #5

Frank,

SWITCH does one test and then knows what to do.

Out of curiosity: any idea, how this is realized?

Karl

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #6

Karl,

This depends on the type of the switch value and the range of values used.
It uses several strategies:
I have seen:
- jumptables based on the values (for example for enums with a small numberof values)
- jumptables based on the hashcode of a string
- sometimes it builds code that looks like a do case / if elseif construct

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #7

Hi Karl,

It depends a lot on the data type of the SWITCH statement, the actual values provided by the user and even by the machine where the code is compiled, because some of the implementation is hidden and done directly from the JITter. In general, I am pretty sure the idea is that this code:

SWITCH n
CASE n == 1
// operation1
CASE n == 2
// operation2
CASE n == 3
// operation3
END

gets translated to something like

aLookUpTable := {AddressOf(operation1) , AddressOf(operation2) , AddressOf(operation3)}
JumpToAddress(aLookUpTable[n])

the array is generated only once at compile time (JIT time actually), so every time this code is executed, only one comparison is made and one jump.

But this is a simplified sample and things get much more complicated if the values provided in the CASE statements are not in order (1,3,2 instead of 1,2,3), if there are gaps in between (1,4,6) or the types of the CASE values is not numeric. Still, the compiler tries to be as smart as possible and still generates efficient code, but in many cases additional jumps are required.

So in general yes, SWITCH is faster (and possibly more self-documenting?) than DO CASE, but the speed difference will be hardly noticeable in most cases, so I wouldn't go crazy replacing every single one of my DO CASEs in my existing code to SWITCH, at least not just for the speed benefit. It could make a big difference in tight loops though, where execution speed is critical. Or in places with a very long list of CASE statements, like in the Dispatch() method of the GUI SDK classes for example.

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #8

Hi Chris,

so I wouldn't go crazy replacing every single one of my DO CASEs in my existing code to SWITCH


after finding my first bug caused by two similar CASE's I replaced all and found a few (one or two) more. It was worth the time.

Frank

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #9

  • wriedmann
  • wriedmann's Avatar
  • Offline
  • Posts: 1426
  • Karma: 6
Hi Frank,

that may be possible for you, but I can replace only very few do case blocks with switch statements.

Please look at this code - do switch will not work:
do case
case oVariante:Anwendbarkeit == ProgSettings.AttributBautiefe 
    oVariante:Einzelpreis := ....
case oVariante:Anwendbarkeit == ProgSettings.AttributHolzArt
    oVariante:Einzelpreis := ....
case oVariante:Anwendbarkeit == ProgSettings.AttributMaterial
    oVariante:Einzelpreis := ....
otherwise         
    oVariante:Einzelpreis := ....
endcase

or this one:
do case
case String.IsNullOrEmpty( _oPosition:NumOrd ) .and. ;
        String.IsNullOrEmpty( _oPosition:NumPre )
    lReturn := false
case _oPosition:Angebot .and. String.IsNullOrEmpty( _oPosition:NumPre )
    lReturn := false
case _oPosition:Angebot
    _cDatabaseFile := Path.Combine( ProgSettings.DatabasePath, ;
        "Pre_" + _oPosition:NumPre + ".db" )
case _oPosition:Angebot == false .and. String.IsNullOrEmpty( _oPosition:NumOrd )
    lReturn := false
case _oPosition:Angebot == false
    _cDatabaseFile := Path.Combine( ProgSettings.DatabasePath, ;
        "Ord_" + _oPosition:NumOrd + ".db" )
case ! String.IsNullOrEmpty( _oPosition:NumPre ) .and. ;
        String.IsNullOrEmpty( _oPosition:NumOrd )
    cDatabaseFile := Path.Combine( ProgSettings.DatabasePath, ;
        "Pre_" + _oPosition:NumPre + ".db" )
case ! String.IsNullOrEmpty( _oPosition:NumOrd )
    cDatabaseFile := Path.Combine( ProgSettings.DatabasePath, ;
        "Ord_" + _oPosition:NumOrd + ".db" )
otherwise
    lReturn := false
endcase

Both are examples from my Door Configurator.

Of course you are right, that a switch is better than a do case, but it is not always possible.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Last edit: by wriedmann. Reason: better formatting

Switch vs do case 1 year 6 months ago #10

Hi Wolfgang,

in generell I agree that not every do case can be replaced by a Switch Statement ...

But why shouldn't your first example be replaced with:

SWITCH oVariante:Anwendbarkeit
CASE ProgSettings.AttributBautiefe
...
CASE ProgSettings.AttributHolzArt
...
CASE ProgSettings.AttributMaterial
...
OTHERWISE
...
END

Just wondering if I'm missing something...

Armin

Please Log in or Create an account to join the conversation.

Last edit: by ArminBack.

Switch vs do case 1 year 6 months ago #11

  • wriedmann
  • wriedmann's Avatar
  • Offline
  • Posts: 1426
  • Karma: 6
Hi Armin,

you can use only constant expressions in switch statements. In my case the compare values are configuration settings.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #12

Wolfgang, Armin,

from help:

switchstmt : (BEGIN|DO)? SWITCH expression eos
(CASE constantexpression eos
statementBlock ) *
(OTHERWISE) eos
statementBlock )?
END SWITCH? garbage? eos


Armin seems to be right. oVariante:Anwendbarkeit is an expression, that will be executed once, ProgSettings.AttributBautiefe looks like a constant to me.

Changing your code, Wolfgang, to something like
local Anwendbarkeit as string // or whatever
Anwendbarkeit := oVariante:Anwendbarkeit
do case
case Anwendbarkeit == ProgSettings.AttributBautiefe

does in important change: it calls oVariante:Anwendbarkeit only once. What if there are sideeffects in this call? What if it causes the execution of thousands of lines of code to evaluate it?

Frank

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #13

  • wriedmann
  • wriedmann's Avatar
  • Offline
  • Posts: 1426
  • Karma: 6
Hi Frank,

the compiler does not consider ProgSettings.AttributBautiefe a constant, and it is not a constant. It could be changed every time (it is a static readonly property that is set at program start).

Yes, I could change my code to not use the property anymore, but use a local variable instead. In my VO code I'm doing this also when the access variables are not strongly typed.

Only Robert or Chris can answer if the use of a (strong typed) property has a performance penalty when compared to a local variable.

Personally I prefer to use the property to have better readable code.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #14

Hi Wolfgang,

Only Robert or Chris can answer if the use of a (strong typed) property has a performance penalty when compared to a local variable.


even a strongly typed property can have thousands of lines of code behind. You don't know. And even if you know at the time you write this CASE block, the implementation of the property may change in the future causing all kinds of problems.

Frank

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #15

Wolfgang,

What Frank said: when compiling the case statement the compiler has no "idea" what code is behind the property. So it will generate a property get call for every expression.
I am sure can imagine a class that counts the # of times a property is read (for example to profile the app). Or a property that returns the time in milliseconds.
If the compiler would automatically "cache" the result of the expression then the result of a do case statement where the property is read more than one time would be quite different from where it is only read one time.

If you as a developer know that it is safe to cache the property, then I would suggest to store it in a local variable.

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #16

  • wriedmann
  • wriedmann's Avatar
  • Offline
  • Posts: 1426
  • Karma: 6
Hi Robert,

thank you very much - I will adjust my code.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #17

Hi
I was not believing it and was comparing the speed btween do case and switch.

result:
switch 6s
docase 10s
VO2.7 13s

switch
//
// The SWITCH statement is a replacement for the DO CASE statement
// The biggest difference is that the expression (in this case sDeveloper) is only evaluated once.
// which will have a performance benefit over the DO CASE statement
//
USING System.Collections.Generic

FUNCTION Start() AS VOID
LOCAL nCnt AS INT
LOCAL nFound AS INT
local nZeit as float

nFound := 0
nZeit := Seconds ()
FOR nCnt := 1 UPTO 10000000
FOREACH VAR sDeveloper IN GetDevelopers()
SWITCH sDeveloper:ToUpper()
CASE "FABRICE"
nFound := nFound +1
CASE "CHRIS"
nFound := nFound +1
CASE "NIKOS"
nFound := nFound +1
CASE "ROBERT"
nFound := nFound +1
OTHERWISE
nFound := nFound +1
END SWITCH
NEXT
NEXT

? nFound:ToString()
? ntrim(seconds ()-nZeit)
Console.ReadKey()
RETURN


FUNCTION GetDevelopers AS List<STRING>
VAR aList := List<STRING>{}
aList:Add("Chris")
aList:Add("Fabrice")
aList:Add("Nikos")
aList:Add("Robert")
aList:Add("The Roslyn Developers")
RETURN aList

do case
USING System.Collections.Generic

FUNCTION Start() AS VOID
LOCAL aList := {} AS ARRAY
LOCAL nCnt AS DWORD
LOCAL nCnt2 AS DWORD
LOCAL nArray AS DWORD
LOCAL cString AS STRING
LOCAL nZeit AS FLOAT
LOCAL nFound AS DWORD

local iTicks as int64

aList := GetDevelopers ()
nArray := ALen (aList)

nFound := 0
nZeit := Seconds ()
FOR nCnt2 := 1 UPTO 10000000
FOR nCnt := 1 UPTO nArray
cString := Upper (aList [nCnt])
DO CASE
CASE cString = "FABRICE"
nFound := nFound +1
CASE cString = "CHRIS"
nFound := nFound +1
CASE cString = "NIKOS"
nFound := nFound +1
CASE cString = "ROBERT"
nFound := nFound +1
OTHERWISE
nFound := nFound +1
ENDCASE
NEXT
NEXT

? nFound:ToString()
? NTrim (Seconds()-nZeit)
Console.ReadKey()
RETURN


FUNCTION GetDevelopers () AS array
local aList as array
aList := {}
AAdd (aList, "Chris")
AAdd (aList, "Farbrice")
AAdd (aList, "Nikos")
AAdd (aList, "Chris")
AAdd (aList, "Robert")
AAdd (aList, "The Roslyn Developers")
RETURN aList

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #18

Hi Horst,

fine but one error. They are the X# developers. Roslyn is made by microsoft.

Please do test the following too

snip
FOR nCnt := 1 UPTO nArray
DO CASE
CASE Upper (aList [nCnt]) = "FABRICE"
nFound := nFound +1
CASE Upper (aList [nCnt]) = "CHRIS"
nFound := nFound +1
snip

Frank

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #19

Hi Frank

26s very bad

Horst

Please Log in or Create an account to join the conversation.

Switch vs do case 1 year 6 months ago #20

Horst,

So switch is definitely faster
Not much but every millisecond counts.
And, like Frank said, it will warn you if you accidentally include the same value twice.
If you really want a good comparison you should change the DO CASE to use the == operator. The single equals = operator in the VO/Vulcan dialect will match "FABRICE" with "F" too.

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

  • Page:
  • 1
  • 2