Switch(case)

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Switch(case)

03 Apr 2018, 18:21

A feature many have asked about, and one that I don't personally care for, but I wrote a function for it anyway. It is different from the standard switch-case visually, but works the same.

Code: Select all

switch(val,cases){
    global switchVal:=val
    
    if(!isObject(cases))
        throw "Second param (cases) must be an object."
    for i,a in cases{
        if(i=="default")
            hasDefault:=1
        else if(val=a){
            if(!isLabel(i))
                throw "Label """ . i . """ doesn't exist."
            else
                gosub % i
            return a
        }
    }
    if(hasDefault){
        if(!isLabel(cases.default))
            throw "Label """ . cases.default . """ doesn't exist."
        else
            gosub % cases.default
        return "default"
    }
    return 0
}
Example:

Code: Select all

var1:=10
var2:=5

loop
    switch(rand(1,10),{label_1:var1
        ,label_2:var2
        ,label_4:9
        ,default:"label_3"})

label_1:
label_2:
label_3:
msgbox % a_thislabel . "`n" . switchVal
return

esc::exitApp

switch(val,cases){
    global switchVal:=val
    
    if(!isObject(cases))
        throw "Second param (cases) must be an object."
    for i,a in cases{
        if(i=="default")
            hasDefault:=1
        else if(val=a){
            if(!isLabel(i))
                throw "Label """ . i . """ doesn't exist."
            else
                gosub % i
            return a
        }
    }
    if(hasDefault){
        if(!isLabel(cases.default))
            throw "Label """ . cases.default . """ doesn't exist."
        else
            gosub % cases.default
        return "default"
    }
    return 0
}

; stdlib
rand(lowerBound,upperBound){
    random,rand,% lowerBound,% upperBound
    return rand
}
The example is meant to be error prone. The best way to avoid such errors is to have an example that has one. ;)

I'll explain in more detail how this works. Foremost, you have the definition, which is switch(val,cases). val will be the value to be checked against. cases will be an object/associative array that has a switch-case like design. The object keys will represent the label to be executed, while the key value will be a value checked against val. In doing this, rather than having it directly in the case name, custom label names may be used. default breaks the convention though; to use default, there must be a key with the name of default. The key value will be the label. I chose to write it this way so "default" may be used as a literal value still.

In the example, the val is a random number between 1 and 10. The case compensates 10, 5, 9, and then default. If it happens to be 5, label_2 will be ran. If it's 10, label_1 will be ran. If it's none of the specified numbers, label_3 is ran. If it's 9, however, it will run label_4. Except, label_4 doesn't exist. This will throw an error and kill the logical thread.

Since it uses an object and literal labels, both the object and labels may be defined anywhere and used whenever needed, thus expanding the limited nature of switch-case, if only slightly.
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Switch(case)

03 Apr 2018, 20:04

I’d recommend adding a check for bound funcs as most people should be utilizing functions instead of labels
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: Switch(case)

03 Apr 2018, 22:12

kczx3 wrote:I’d recommend adding a check for bound funcs as most people should be utilizing functions instead of labels
Unlikely. It's suppose to be similar to a switch-case, where the use of functions would deviate greatly, seeing as they use labels. It could accommodate for function names directly, which I did consider, but objects can't be keys, therefore bound functions will not work with this approach.
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Switch(case)

04 Apr 2018, 00:12

Edit: This post contains misinformation, please see below.
I agree that labels are more suitable, but you can use any object as a key in an associative array, eg, obj[[]] := .... In a literal object definition, for keys, you need to enclose expressions in parentheses, eg {(func("f").bind()):val}.

I think the switch case is a fun game with the language syntax, more than being actually useful or convenient, as a built in alternative would be, thanks for sharing :thumbup:.

Cheers.
Last edited by Helgef on 06 Apr 2018, 09:38, edited 1 time in total.
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: Switch(case)

04 Apr 2018, 00:41

Helgef wrote:In a literal object definition, for keys, you need to enclose expressions in parentheses, eg {(func("f").bind()):val}.
That's.. I mean, that just seems like a poor idea. I clearly stand corrected, but specifying a bound function as an associative key seems unintuitive, unless I'm missing something.

As for having an actual implementation of switch-case, it's been asked for a number of years so probably won't come around, but also I really couldn't care any less. It's not a structure I would ever use practically. I just got bored :lol:
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
User avatar
Relayer
Posts: 160
Joined: 30 Sep 2013, 13:09
Location: Delaware, USA

Re: Switch(case)

04 Apr 2018, 08:45

This uses labels but I like the simplicity and the form as it mimics a nominal switch statement rather well.

Code: Select all

foo := "yada yada"
Loop 1 ;switch
{
	Goto % IsLabel("Case(" . foo . ")") ? "Case(" . foo . ")" : "Case_Default"
	Case(yada yada):
	{
	}
	Break
	Case_Default:
	{
	}
	Break
}
Relayer
lexikos
Posts: 9552
Joined: 30 Sep 2013, 04:07
Contact:

Re: Switch(case)

06 Apr 2018, 02:51

@Helgef
Using the {key:value} notation, quote marks are optional for keys which consist only of word characters. Any expression can be used as a key, but to use a variable as a key, it must be enclosed in parentheses. For example, {(KeyVar): Value} and {GetKey(): Value} are both valid.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Switch(case)

06 Apr 2018, 09:37

Thank you for the correction lexikos.
Thanks for sharing Relayer. :thumbup:

Cheers.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 109 guests