"Sputnik" help  
Sputnik Help
Given(<value>, [<strict>], [<comparison>]) { <givenStatements> }
Given(<value>, [<strict>], [<comparison>]) use(<variables>) { <givenStatements> }

Description

Executes a set of statements based on the provided value, akin to a switch/case or match construct in other languages. Notably, comparisons within given are strict by default, ensuring precise type and value matching. The optional second parameter allows users to control the strictness behavior, offering flexibility in interpreting input types. The optional third parameter allows a callback to be executed to handle the comparison of every match aside from ones that have their own dedicated handler.

Parameters

<value> The value to be evaluated for matching.
<strict> Optional. If true the comparison will be strict. Default: true.
<comparison> Optional. If provided the callback can be used to handle the comparison of any match without its own handler. Default: null.
<variables> Optional. The use() is optional it's purpose is to fetch variables inside the given statement from outside of it.
<givenStatements> A set of statements defining cases and actions based on the input value.

Return Value

The result of the matched case or the default case if no match is found. If none found and no default exists will return null.

Remarks

The given statement allows for concise and expressive control flow based on the input value. It is particularly useful for scenarios where you need to check multiple cases against a single value.

This simplifies the process of handling multiple cases based on a single value. It supports various types of comparisons, including custom comparison blocks and functions, making it a versatile construct in Sputnik.

Comparisons are strict.

Overview

The given statement in Sputnik is a powerful and flexible control flow construct designed to enhance readability and simplify complex conditional logic. It provides a clear and concise way to handle multiple cases based on the value of a given expression. Unlike traditional switch or if-else structures, the given statement promotes a more expressive and intuitive coding style.

Key Features and Benefits

1. Readability and Conciseness
The primary advantage of the given statement lies in its ability to make code more readable and concise. By organizing cases in a block associated with the given expression, developers can easily understand the logic flow without the need for nested structures or excessive indentation.

2. Improved Code Organization
The given statement encourages a cleaner organization of code, especially when dealing with numerous cases. Each case is presented in a clear and isolated manner within the block, contributing to better code structure and maintenance.

3. Enhanced Expressiveness
The given statement is highly expressive, allowing developers to specify multiple values or ranges for a single case. This flexibility enables concise representation of complex conditions, resulting in more straightforward and comprehensible code.

4. Default Case Handling
In addition to handling specific cases, the given statement includes a default case that executes when none of the specified cases match the input value. This default case provides a convenient way to handle unexpected or unhandled scenarios.

5. Custom Comparison Callback
Sputnik's given statement supports custom comparison callback, allowing developers to define their own comparison callback logic for intricate matching requirements across all matches at once (aside from ones that have their own comparison block). This feature enhances the versatility of the given statement, enabling tailored solutions for various use cases.

6. Custom Comparison Blocks
Sputnik's given statement supports custom comparison blocks, allowing developers to define their own comparison logic for intricate matching requirements. This feature enhances the versatility of the given statement, enabling tailored solutions for various use cases.

7. Access to Input Value
The given statement introduces the $value variable, providing easy access to the input value within the block. This allows developers to reference the input value dynamically, enhancing the context-awareness of the code.

8. The $a and $b:
Within the given statement, when using custom comparison blocks, the variables $a and $b are automatically created. These variables play a crucial role in the comparison blocks, where $a represents the given argument (the input value), and $b represents the current value being checked against the cases.

9. The $cmp Variable:
In the context of the given statement with custom comparison blocks, the $cmp variable plays a significant role. This variable represents the result of the comparison conducted within the given block. The introduction of $cmp enhances the ability of developers to capture and utilize the outcome of the custom comparisons.

10. Seamless Integration with Functions and Macros
Developers can seamlessly integrate functions and macros within given blocks, expanding the capabilities of this statement. This integration enables dynamic case evaluation based on custom functions, contributing to a more modular and extensible codebase.

11. Enhanced Flexibility with use Clause
The given statement in Sputnik introduces an advanced level of flexibility through the innovative use of the use clause (use()). This clause allows developers to fetch variables from the surrounding scope directly into the given block, empowering the statement to dynamically access external variables during case evaluations.The use clause enhances the versatility of the given statement by providing access to external variables, empowering developers to create more modular and adaptable code. This flexibility proves particularly beneficial when case evaluations depend on dynamic or external criteria, contributing to a more expressive and powerful programming experience.

Use Cases

The given statement is particularly useful in scenarios where:

Conclusion

The given statement in Sputnik is a valuable tool for developers seeking a more expressive, readable, and organized approach to conditional logic. Its features, such as custom comparison blocks, default case handling, and seamless integration with functions, contribute to a robust and versatile control flow mechanism. By adopting the given statement, developers can enhance code quality, reduce complexity, and improve the overall maintainability of their Sputnik programs.

Related

Example

Basic example:

say given(10)
{
    10: "it is 10";
    20: "it is 20";
    30: "it is 30";
};
// PRINTS
// it is 10

Why given is useful? See this code using a Switch statement:

Function ResolveStatus($statusCode)
{
    my $message;
    switch ($statusCode)
    {
        case 200:
        case 300:
            $message = undef;
            break;
        case 400:
            $message = "not found";
            break;
        case 500:
            $message = "server error";
            break;
        default:
            $message = "unknown status code";
            break;
    }
    return $message;
}

say ResolveStatus(200);
say ResolveStatus(300);
say ResolveStatus(400);
say ResolveStatus(500);
say ResolveStatus(600);

// PRINTS
// 
// 
// not found
// server error
// unknown status code

Now lets remake it using the Given statement:

Function ResolveStatus($statusCode)
{
    my $message = given($statusCode)
    {
        200, 300: undef;
        400: "not found";
        500: "server error";
        default: "unknown status code";
    };
    return $message;
}

say ResolveStatus(200);
say ResolveStatus(300);
say ResolveStatus(400);
say ResolveStatus(500);
say ResolveStatus(600);

// PRINTS
// 
// 
// not found
// server error
// unknown status code
Much easier to read.

Supports multiple values to match at once:

say given(20)
{
    10, 20, 30: "it is 10, 20 or 30";
};
// PRINTS
// it is 20

Supports a default:

say given(40)
{
    10, 20, 30: "it is 10, 20 or 30";
    default: "no idea!";
};
// PRINTS
// no idea!

Accessing the input $value:

say given(40)
{
    10, 20, 30: "it is 10, 20 or 30";
    default: "your $value is not valid here!";
};
// PRINTS
// your 40 is not valid here!

Works with any value type even strings:

say given("fox")
{
    "cat", "dog", "fox": "your favourite animal is a $value how nice!";
    default: "error";
};
// PRINTS
// your favourite animal is a fox how nice!

The comparison in given statements are strict however we can make them normal with by making the strict parameter false:

say given(77)
{
    "77": "it is seven seven as string";
    77: "it is seven seven as numeric";
    default: "error";
};
// PRINTS
// it is seven seven as numeric

say given(77, false)
{
    "77": "it is seven seven as string";
    77: "it is seven seven as numeric";
    default: "error";
};
// PRINTS
// it is seven seven as string

We can define our own comparison logic using a callback as shown here:

Function Testy($str)
{
    my $res = given($str, undef, {{ ($a + 1) eq $b; }})
    {
        101: "it is 101";
        201: "it is 102";
    };
    return $res;
}

say Testy(100);
say Testy(200);

// PRINTS
// it is 101
// it is 102

Notice the callback is checking if the lhs (input value) +1 is equal to the rhs (match value) this callback system allows very fine tuning how the matches should take place.

Similar to above but this time doing the comparisons using the cmp operator:

Function Testy($str)
{
    my $res = given($str, undef, {{ ($a cmp $b) == 0; }})
    {
        101: "it is 101";
        201: "it is 102";
    };
    return $res;
}

say Testy(101);
say Testy(201);

// PRINTS
// it is 101
// it is 102
As you can see you can make the comparison however you wish.

Heres a comparison between an If statement and a Given statement:

// using IF
Function SelectAnimalId1($animal)
{
    if ($animal == "cat")
        return 10;
    else if ($animal == "dog")
        return 20;
    else if ($animal == "fox")
        return 30;
    else
        return -1;
}

// using GIVEN
Function SelectAnimalId2($animal)
{
    return given($animal)
    {
        "cat": 10;
        "dog": 20;
        "fox": 30;
        default: -1;
    };
}

say SelectAnimalId1("dog");
say SelectAnimalId2("dog");
// PRINTS
// 20
// 20

In the SelectAnimalId1 function, traditional if-else statements are used to determine the animal ID based on the input. The output for the input "dog" is 20, as expected.

In the SelectAnimalId2 function, the given statement provides a more concise and readable alternative. The output for the input "dog" is also 20, demonstrating that the given statement produces the same result with a more compact syntax.

This example showcase how the given statement simplifies the code structure, making it more straightforward and easier to maintain compared to traditional branching with if-else statements.

The comparison is strict so this will be detected as numeric:

say given(77)
{
    "77": "it is seven seven as string";
    77: "it is seven seven as numeric";
    default: "error";
};
// PRINTS
// it is seven seven as numeric

Anything can returned given including classes:

class cat
{
    Function Action()
    {
        say "Meow";
    }
}
class dog
{
    Function Action()
    {
        say "Woof";
    }
}

my $a = given("cat")
{
    "cat": new cat();
    "dog": new dog();
    default: "error";
};
$a->Action();
// PRINTS
// Meow

We can use functions for the comparison:

Function MyCompare($a, $b)
{
    return ($a + 1) == $b;
}

say given(7)
{
    {MyCompare($a, $b);} 8: "the input was able to become 8";
    default: "error";
};
// PRINTS
// the input was able to become 8

We can get the result of the comparison too:

Function MyCompare($a, $b)
{
    if (($a + 1) == $b)
        return $a + 1;
    return false;
}

say given(7)
{
    {MyCompare($a, $b);} 8: "the input was $value but it became $cmp";
    default: "error";
};
// PRINTS
// the input was 7 but it became 8

We can also get the comparison values as well:

Function MyCompare($a, $b)
{
    if (($a + 1) == $b)
        return $a + 1;
    return false;
}

say given(7)
{
    {MyCompare($a, $b);} 8: "the input was $value but it became $cm ($a == $b)";
    default: "error";
};
// PRINTS
// the input was 7 but it became  (7 == 8)

An interesting example using the Match function:

Function GetMatch($txt)
{
    return given($txt)
    {
        match($value, "%d+"): "numeric";
        match($value, "%a+"): "letters";
        default: -1;
    };
}

say GetMatch("777");
say GetMatch("cat");
// PRINTS
// numeric
// letters

In that example the GetMatch function utilizes the given statement to categorize the input $txt based on specific patterns using the match function.

In the first call to GetMatch("777"), the input matches the numeric pattern %d+, resulting in the output "numeric."

In the second call to GetMatch("cat"), the input matches the letters pattern %a+, resulting in the output "letters."

This showcases how the combination of the given statement and pattern matching with the match function allows for a concise and expressive way to categorize input based on specific criteria. The code is more readable and focused on the conditions, making it easier to understand and maintain.

Same as above but using regex match:

Function GetMatch($txt)
{
    return given($txt)
    {
        $value =~ m/\d+/ ? $value : null: "numeric";
        $value =~ m/\w+/ ? $value : null: "letters";
        default: -1;
    };
}

say GetMatch("777");
say GetMatch("cat");
// PRINTS
// numeric
// letters

In this example the GetMatch function, the given statement is used with custom conditions that involve pattern matching using regular expressions.

For the first case, $value =~ m/\d+/ ? $value : null checks if the input contains numeric characters. If true, it returns the numeric value; otherwise, it returns null.

For the second case, $value =~ m/\w+/ ? $value : null checks if the input contains alphanumeric characters. If true, it returns the alphanumeric value; otherwise, it returns null.

The default case handles scenarios where the input does not match any of the specified patterns, returning -1.

In the say statements, the function is called with "777" and "cat" as inputs, resulting in the categorization of "numeric" and "letters," respectively.

This example showcases the versatility of the given statement in handling complex conditions, incorporating pattern matching directly into the decision-making process. It contributes to more readable and concise code, especially in scenarios involving intricate logic and pattern-based categorization.

Same as above but using the code block to change how the comparison is made:

Function GetMatch($txt)
{
    return given($txt)
    {
        {IsTrue($b);} $value =~ m/\d+/: "numeric";
        {IsTrue($b);} $value =~ m/\w+/: "letters";
        default: -1;
    };
}

say GetMatch("777");
say GetMatch("cat");
// PRINTS
// numeric
// letters

In this intriguing example the given statement is leveraged with custom conditions, eliminating the need for the traditional ternary operator ? :. Within the given block, conditions are defined using custom blocks such as {IsTrue($b);}, dynamically evaluating the result of the IsTrue($b) function. Depending on the outcome, the subsequent pattern-matching conditions like $value =~ m/\d+/ and $value =~ m/\w+/ are followed by a colon : to determine the result. This creative approach streamlines the conditional logic within the given statement, showcasing the expressive power of Sputnik's syntax in handling complex pattern matching scenarios.

Similar to above but even more weird:

Function GetMatch($txt)
{
    return given($txt)
    {
        {$a =~ m/\d+/;} null: "numeric";
        {$a =~ m/\w+/;} null: "letters";
        default: -1;
    };
}

say GetMatch("777");
say GetMatch("cat");
// PRINTS
// numeric
// letters

In this rather intriguing example the given statement is utilized in a unique way, bypassing the need for a check value and relying solely on custom comparisons within the conditions. Within the given block, custom blocks such as {$a =~ m/\d+/;} null and {$a =~ m/\w+/;} null are employed for intricate pattern matching without an explicit boolean check. The subsequent null values act as placeholders, and the desired results "numeric" and "letters" are directly returned based on the success of the custom comparisons. This unconventional use showcases the flexibility and unconventional possibilities offered by Sputnik's syntax in crafting concise and expressive code for intricate pattern matching scenarios.

Using a macro:

class cat
{
    Function Action()
    {
        say "Meow";
    }
}
class dog
{
    Function Action()
    {
        say "Woof";
    }
}

#define ANIMAL(x) @{{ given(x) { "cat": new cat(); "dog": new dog(); default: null; }; }}

ANIMAL("cat")->Action();
ANIMAL("dog")->Action();
// PRINTS // meow
// woof

Make the macro easier to read:

class cat
{
    Function Action()
    {
        say "Meow";
    }
}
class dog
{
    Function Action()
    {
        say "Woof";
    }
}

#define ANIMAL(x) @{{ given(x) { \
                        "cat": new cat(); \
                        "dog": new dog(); \
                        default: null; \
                    }; }}

ANIMAL("cat")->Action();
ANIMAL("dog")->Action();
// PRINTS // meow
// woof

Make the macro super easy to read:

class cat
{
    Function Action()
    {
        say "Meow";
    }
}
class dog
{
    Function Action()
    {
        say "Woof";
    }
}

#macro ANIMAL(x)
@{{
    given(x)
    {
        "cat": new cat();
        "dog": new dog();
        default: null;
    };
}}
#endm

ANIMAL("cat")->Action();
ANIMAL("dog")->Action();
// PRINTS // meow
// woof

You can also bring in variables from outside the given statement using the use() statement as shown here:

my $num = 77;
my $result = given(true) use ($num)
{
    $num >= 60: "60 or higher ($num)";
    $num >= 40: "40 or higher ($num)";
    $num >= 20: "20 or higher ($num)";
    default: "below 20 ($num)";
};
say $result;
// PRINTS
// 60 or higher (77)

The use ($num) allows the $num variable to be fetched inside the given statement.

This supports multiple variable usage and even defaults:

my $num = 77;
my $cat = "meow";
my $result = given(true) use ($num, $cat, $dog = "woof")
{
    $num >= 60: "60 or higher ($num) - $cat -> $dog";
    $num >= 40: "40 or higher ($num) - $cat -> $dog";
    $num >= 20: "20 or higher ($num) - $cat -> $dog";
    default: "below 20 ($num) - $cat -> $dog";
};
say $result;
// PRINTS
// 60 or higher (77) - meow -> woof
In Summary

The given statement in Sputnik offers developers a powerful and expressive way to handle multiple cases based on a single input value. With access to the $value variable, developers can dynamically reference the input value within the block, enhancing context-awareness. Additionally, the automatically generated $a and $b variables facilitate custom comparison blocks.

The introduction of $cmp further enriches the given statement by providing a variable to capture the result of custom comparisons. This allows developers to not only determine case matches but also obtain specific information from the comparison operation, enabling more nuanced and detailed case handling.

In essence, the given statement simplifies complex conditional logic, promotes code readability, and offers flexibility through dynamic referencing and custom comparisons, making it a valuable construct for developers in Sputnik programming.


Contact
Cheryl (uberfox@hotmail.com)
Homepage
http://ubersoft.org