Add switch expression.
This commit is contained in:
@@ -12,27 +12,19 @@ Use `type_of()` to Get Value Type
|
||||
Because [`type_of()`] a `Dynamic` value returns the type of the actual value,
|
||||
it is usually used to perform type-specific actions based on the actual value's type.
|
||||
|
||||
```rust
|
||||
```c
|
||||
let mystery = get_some_dynamic_value();
|
||||
|
||||
if type_of(mystery) == "i64" {
|
||||
print("Hey, I got an integer here!");
|
||||
} else if type_of(mystery) == "f64" {
|
||||
print("Hey, I got a float here!");
|
||||
} else if type_of(mystery) == "string" {
|
||||
print("Hey, I got a string here!");
|
||||
} else if type_of(mystery) == "bool" {
|
||||
print("Hey, I got a boolean here!");
|
||||
} else if type_of(mystery) == "array" {
|
||||
print("Hey, I got an array here!");
|
||||
} else if type_of(mystery) == "map" {
|
||||
print("Hey, I got an object map here!");
|
||||
} else if type_of(mystery) == "Fn" {
|
||||
print("Hey, I got a function pointer here!");
|
||||
} else if type_of(mystery) == "TestStruct" {
|
||||
print("Hey, I got the TestStruct custom type here!");
|
||||
} else {
|
||||
print("I don't know what this is: " + type_of(mystery));
|
||||
switch mystery {
|
||||
"i64" => print("Hey, I got an integer here!"),
|
||||
"f64" => print("Hey, I got a float here!"),
|
||||
"string" => print("Hey, I got a string here!"),
|
||||
"bool" => print("Hey, I got a boolean here!"),
|
||||
"array" => print("Hey, I got an array here!"),
|
||||
"map" => print("Hey, I got an object map here!"),
|
||||
"Fn" => print("Hey, I got a function pointer here!"),
|
||||
"TestStruct" => print("Hey, I got the TestStruct custom type here!"),
|
||||
_ => print("I don't know what this is: " + type_of(mystery))
|
||||
}
|
||||
```
|
||||
|
||||
|
97
doc/src/language/switch.md
Normal file
97
doc/src/language/switch.md
Normal file
@@ -0,0 +1,97 @@
|
||||
`switch` Expression
|
||||
===================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
The `switch` _expression_ allows matching on literal values, and it mostly follows Rust's
|
||||
`match` syntax:
|
||||
|
||||
```c
|
||||
switch calc_secret_value(x) {
|
||||
1 => print("It's one!"),
|
||||
2 => {
|
||||
print("It's two!");
|
||||
print("Again!");
|
||||
}
|
||||
3 => print("Go!"),
|
||||
// _ is the default when no cases match
|
||||
_ => print("Oops! Something's wrong: " + x)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Expression, Not Statement
|
||||
------------------------
|
||||
|
||||
`switch` is not a statement, but an expression. This means that a `switch` expression can
|
||||
appear anywhere a regular expression can, e.g. as function call arguments.
|
||||
|
||||
```c
|
||||
let x = switch foo { 1 => true, _ => false };
|
||||
|
||||
func(switch foo {
|
||||
"hello" => 42,
|
||||
"world" => 123,
|
||||
_ => 0
|
||||
});
|
||||
|
||||
// The above is somewhat equivalent to:
|
||||
|
||||
let x = if foo == 1 { true } else { false };
|
||||
|
||||
if foo == "hello" {
|
||||
func(42);
|
||||
} else if foo == "world" {
|
||||
func(123);
|
||||
} else {
|
||||
func(0);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Array and Object Map Literals Also Work
|
||||
--------------------------------------
|
||||
|
||||
The `switch` expression can match against any _literal_, including [array] and [object map] literals.
|
||||
|
||||
```c
|
||||
// Match on arrays
|
||||
switch [foo, bar, baz] {
|
||||
["hello", 42, true] => { ... }
|
||||
["hello", 123, false] => { ... }
|
||||
["world", 1, true] => { ... }
|
||||
_ => { ... }
|
||||
}
|
||||
|
||||
// Match on object maps
|
||||
switch map {
|
||||
#{ a: 1, b: 2, c: true } => { ... }
|
||||
#{ a: 42, d: "hello" } => { ... }
|
||||
_ => { ... }
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Difference From If-Else Chain
|
||||
-----------------------------
|
||||
|
||||
Although a `switch` expression looks _almost_ the same as an `if`-`else` chain,
|
||||
there are subtle differences between the two.
|
||||
|
||||
A `switch` expression matches through _hashing_ via a look-up table.
|
||||
Therefore, matching is very fast. Walking down an `if`-`else` chain
|
||||
will be _much_ slower.
|
||||
|
||||
On the other hand, operators can be [overloaded][operator overloading] in Rhai,
|
||||
meaning that it is possible to override the `==` operator for integers such
|
||||
that `if x == y` returns a different result from the built-in default.
|
||||
|
||||
`switch` expressions do _not_ use the `==` operator for comparison;
|
||||
instead, they _hash_ the data values and jump directly to the correct
|
||||
statements via a pre-compiled look-up table. This makes matching extremely
|
||||
efficient, but it also means that [overloading][operator overloading]
|
||||
the `==` operator will have no effect.
|
||||
|
||||
Therefore, in environments where it is desirable to [overload][operator overloading]
|
||||
the `==` operator - though it is difficult to think of valid scenarios where you'd want
|
||||
`1 == 1` to return something other than `true` - avoid using the `switch` expression.
|
Reference in New Issue
Block a user