reorganize module
This commit is contained in:
76
_archive/rhai_engine/rhaibook/rust/immutable-string.md
Normal file
76
_archive/rhai_engine/rhaibook/rust/immutable-string.md
Normal file
@@ -0,0 +1,76 @@
|
||||
The `ImmutableString` Type
|
||||
==========================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
~~~admonish question.side "Why `SmartString`?"
|
||||
|
||||
[`SmartString`] is used because many strings in scripts are short (fewer than 24 ASCII characters).
|
||||
~~~
|
||||
|
||||
All [strings] in Rhai are implemented as `ImmutableString`, which is an alias to
|
||||
`Rc<SmartString>` (or `Arc<SmartString>` under the [`sync`] feature).
|
||||
|
||||
An `ImmutableString` is immutable (i.e. never changes) and therefore can be shared among many users.
|
||||
Cloning an `ImmutableString` is cheap since it only copies an immutable reference.
|
||||
|
||||
Modifying an `ImmutableString` causes it first to be cloned, and then the modification made to the copy.
|
||||
Therefore, direct string modifications are expensive.
|
||||
|
||||
|
||||
Avoid `String` Parameters
|
||||
-------------------------
|
||||
|
||||
`ImmutableString` should be used in place of `String` for function parameters because using `String`
|
||||
is very inefficient (the argument is cloned during every function call).
|
||||
|
||||
A alternative is to use `&str` which de-sugars to `ImmutableString`.
|
||||
|
||||
A function with the first parameter being `&mut String` does not match a string argument passed to it,
|
||||
which has type `ImmutableString`. In fact, `&mut String` is treated as an opaque [custom type].
|
||||
|
||||
```rust
|
||||
fn slow(s: String) -> i64 { ... } // string is cloned each call
|
||||
|
||||
fn fast1(s: ImmutableString) -> i64 { ... } // cloning 'ImmutableString' is cheap
|
||||
|
||||
fn fast2(s: &str) -> i64 { ... } // de-sugars to above
|
||||
|
||||
fn bad(s: &mut String) { ... } // '&mut String' will not match string values
|
||||
```
|
||||
|
||||
|
||||
Differences from Rust Strings
|
||||
-----------------------------
|
||||
|
||||
Internally Rhai strings are stored as UTF-8 just like Rust (they _are_ Rust `String`s!),
|
||||
but nevertheless there are major differences.
|
||||
|
||||
In Rhai a [string] is semantically the same as an array of Unicode characters and can be directly
|
||||
indexed (unlike Rust).
|
||||
|
||||
This is similar to most other languages (e.g. JavaScript, C#) where strings are stored internally
|
||||
not as UTF-8 but as arrays of UCS-16 or UCS-32.
|
||||
|
||||
Individual characters within a Rhai string can also be replaced just as if the string is an array of
|
||||
Unicode characters.
|
||||
|
||||
In Rhai, there are also no separate concepts of `String` and `&str` (a string slice) as in Rust.
|
||||
|
||||
|
||||
```admonish warning "Performance considerations"
|
||||
|
||||
Although Rhai exposes a [string] as a simple array of [characters] which can be directly indexed to
|
||||
get at a particular [character], such convenient syntax is an _illusion_.
|
||||
|
||||
Internally the [string] is still stored in UTF-8 (native Rust `String`s).
|
||||
|
||||
All indexing operations actually require walking through the entire UTF-8 string to find the offset
|
||||
of the particular [character] position, and therefore is _much_ slower than the simple array
|
||||
indexing for other scripting languages.
|
||||
|
||||
This implementation detail is hidden from the user but has a performance implication.
|
||||
|
||||
Avoid large scale [character]-based processing of [strings]; instead, build an actual [array] of
|
||||
[characters] (via the `split()` method) which can then be manipulated efficiently.
|
||||
```
|
Reference in New Issue
Block a user