Refine string docs.
This commit is contained in:
parent
abf66850f6
commit
e103c8e66c
@ -20,9 +20,14 @@ The `ImmutableString` Type
|
||||
-------------------------
|
||||
|
||||
All strings in Rhai are implemented as `ImmutableString` (see [standard types]).
|
||||
An `ImmutableString` does not change and can be shared.
|
||||
|
||||
`ImmutableString` should be used in place of the standard Rust type `String` when registering functions
|
||||
because using `String` is very inefficient (the `String` must always be cloned).
|
||||
Modifying an `ImmutableString` causes it first to be cloned, and then the modification made to the copy.
|
||||
|
||||
### **IMPORTANT** - Avoid `String` Parameters
|
||||
|
||||
`ImmutableString` should be used in place of `String` for function parameters because using
|
||||
`String` is very inefficient (the `String` argument is cloned during every call).
|
||||
|
||||
A alternative is to use `&str` which maps straight to `ImmutableString`.
|
||||
|
||||
@ -67,14 +72,6 @@ Individual characters within a Rhai string can also be replaced just as if the s
|
||||
In Rhai, there are also no separate concepts of `String` and `&str` as in Rust.
|
||||
|
||||
|
||||
Immutable Strings
|
||||
----------------
|
||||
|
||||
Rhai use _immutable_ strings (type `ImmutableString`) and can be shared.
|
||||
|
||||
Modifying a Rhai string actually causes it first to be cloned, and then the modification made to the copy.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
|
@ -14,7 +14,7 @@ The following primitive types are supported natively:
|
||||
| **Immutable Unicode [string]** | `rhai::ImmutableString` (implemented as `Rc<String>` or `Arc<String>`) | `"string"` | `"hello"` etc. |
|
||||
| **[`Array`]** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | `"[ ?, ?, ? ]"` |
|
||||
| **[Object map]** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | `"#{ "a": 1, "b": 2 }"` |
|
||||
| **[Timestamp]** (implemented in the [`BasicTimePackage`][packages], disabled with [`no_std`]) | `std::time::Instant` ([`instant::Instant`] if not [WASM] build) | `"timestamp"` | _not supported_ |
|
||||
| **[Timestamp]** (implemented in the [`BasicTimePackage`][packages], disabled with [`no_std`]) | `std::time::Instant` ([`instant::Instant`] if [WASM] build) | `"timestamp"` | _not supported_ |
|
||||
| **[Function pointer]** | `rhai::FnPtr` | `Fn` | `"Fn(foo)"` |
|
||||
| **[`Dynamic`] value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | _actual value_ |
|
||||
| **System integer** (current configuration) | `rhai::INT` (`i32` or `i64`) | `"i32"` or `"i64"` | `"42"`, `"123"` etc. |
|
||||
|
@ -4,19 +4,32 @@
|
||||
{{#include ../links.md}}
|
||||
|
||||
|
||||
Avoid `String`
|
||||
--------------
|
||||
|
||||
As must as possible, avoid using `String` parameters in functions.
|
||||
|
||||
Each `String` argument is cloned during every single call to that function - and the copy
|
||||
immediately thrown away right after the call.
|
||||
|
||||
Needless to say, it is _extremely_ inefficient to use `String` parameters.
|
||||
|
||||
|
||||
`&str` Maps to `ImmutableString`
|
||||
-------------------------------
|
||||
|
||||
Rust functions accepting parameters of `String` should use `&str` instead because it maps directly to
|
||||
[`ImmutableString`][string] which is the type that Rhai uses to represent [strings] internally.
|
||||
|
||||
The parameter type `String` is discouraged because it involves converting an [`ImmutableString`] into a `String`.
|
||||
The parameter type `String` involves always converting an [`ImmutableString`][string] into a `String`
|
||||
which mandates cloning it.
|
||||
|
||||
Using `ImmutableString` or `&str` is much more efficient.
|
||||
A common mistake made by novice Rhai users is to register functions with `String` parameters.
|
||||
|
||||
```rust
|
||||
fn get_len1(s: String) -> i64 { s.len() as i64 } // <- Rhai finds this function, but very inefficient
|
||||
fn get_len2(s: &str) -> i64 { s.len() as i64 } // <- Rhai finds this function fine
|
||||
fn get_len1(s: String) -> i64 { s.len() as i64 } // <- Very inefficient!!!
|
||||
fn get_len2(s: &str) -> i64 { s.len() as i64 } // <- This is better
|
||||
fn get_len3(s: ImmutableString) -> i64 { s.len() as i64 } // <- the above is equivalent to this
|
||||
|
||||
engine
|
||||
@ -24,9 +37,9 @@ engine
|
||||
.register_fn("len2", get_len2)
|
||||
.register_fn("len3", get_len3);
|
||||
|
||||
let len = engine.eval::<i64>("x.len1()")?; // error: function 'len1 (&str | ImmutableString)' not found
|
||||
let len = engine.eval::<i64>("x.len2()")?; // works fine
|
||||
let len = engine.eval::<i64>("x.len3()")?; // works fine
|
||||
let len = engine.eval::<i64>("x.len1()")?; // 'x' is cloned, very inefficient!
|
||||
let len = engine.eval::<i64>("x.len2()")?; // 'x' is shared
|
||||
let len = engine.eval::<i64>("x.len3()")?; // 'x' is shared
|
||||
```
|
||||
|
||||
|
||||
@ -37,9 +50,11 @@ Rhai functions can take a first `&mut` parameter. Usually this is a good idea b
|
||||
cloning of the argument (except for primary types where cloning is cheap), so its use is encouraged
|
||||
even though there is no intention to ever mutate that argument.
|
||||
|
||||
`ImmutableString` is an exception to this rule. While `ImmutableString` is cheap to clone (only
|
||||
incrementing a reference count), taking a mutable reference to it involves making a private clone
|
||||
of the underlying string because Rhai has no way to find out whether that parameter will be mutated.
|
||||
[`ImmutableString`][string] is an exception to this rule.
|
||||
|
||||
While `ImmutableString` is cheap to clone (only incrementing a reference count), taking a mutable
|
||||
reference to it involves making a private clone of the underlying string because Rhai has no way
|
||||
to find out whether that parameter will be mutated.
|
||||
|
||||
If the `ImmutableString` is not shared by any other variables, then Rhai just returns a mutable
|
||||
reference to it since nobody else is watching! Otherwise a private copy is made first,
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Module containing implementation for custom syntax.
|
||||
use crate::any::Dynamic;
|
||||
use crate::engine::{Engine, Imports, State, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||
use crate::error::{LexError, ParseError, ParseErrorType};
|
||||
use crate::error::{LexError, ParseError};
|
||||
use crate::fn_native::{SendSync, Shared};
|
||||
use crate::module::Module;
|
||||
use crate::parser::Expr;
|
||||
|
Loading…
Reference in New Issue
Block a user