Add iterator support for strings.
This commit is contained in:
parent
4603f8026f
commit
ff37e02443
16
README.md
16
README.md
@ -1499,6 +1499,11 @@ record == "Bob X. Davis: age 42 ❤\n";
|
|||||||
"Davis" in record == true;
|
"Davis" in record == true;
|
||||||
'X' in record == true;
|
'X' in record == true;
|
||||||
'C' in record == false;
|
'C' in record == false;
|
||||||
|
|
||||||
|
// Strings can be iterated with a 'for' statement, yielding characters
|
||||||
|
for ch in record {
|
||||||
|
print(ch);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The maximum allowed length of a string can be controlled via `Engine::set_max_string_size`
|
The maximum allowed length of a string can be controlled via `Engine::set_max_string_size`
|
||||||
@ -2011,9 +2016,18 @@ loop {
|
|||||||
Iterating through a range or an [array] is provided by the `for` ... `in` loop.
|
Iterating through a range or an [array] is provided by the `for` ... `in` loop.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let array = [1, 3, 5, 7, 9, 42];
|
// Iterate through string, yielding characters
|
||||||
|
let s = "hello, world!";
|
||||||
|
|
||||||
|
for ch in s {
|
||||||
|
if ch > 'z' { continue; } // skip to the next iteration
|
||||||
|
print(ch);
|
||||||
|
if x == '@' { break; } // break out of for loop
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate through array
|
// Iterate through array
|
||||||
|
let array = [1, 3, 5, 7, 9, 42];
|
||||||
|
|
||||||
for x in array {
|
for x in array {
|
||||||
if x > 10 { continue; } // skip to the next iteration
|
if x > 10 { continue; } // skip to the next iteration
|
||||||
print(x);
|
print(x);
|
||||||
|
@ -125,7 +125,7 @@ fn main() {
|
|||||||
|
|
||||||
match engine
|
match engine
|
||||||
.compile_with_scope(&scope, &script)
|
.compile_with_scope(&scope, &script)
|
||||||
.map_err(|err| err.into())
|
.map_err(Into::into)
|
||||||
.and_then(|r| {
|
.and_then(|r| {
|
||||||
ast_u = r.clone();
|
ast_u = r.clone();
|
||||||
|
|
||||||
|
@ -2265,14 +2265,14 @@ fn run_builtin_binary_op(
|
|||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
match op {
|
match op {
|
||||||
"+" => return add(x, y).map(Into::<Dynamic>::into).map(Some),
|
"+" => return add(x, y).map(Into::into).map(Some),
|
||||||
"-" => return sub(x, y).map(Into::<Dynamic>::into).map(Some),
|
"-" => return sub(x, y).map(Into::into).map(Some),
|
||||||
"*" => return mul(x, y).map(Into::<Dynamic>::into).map(Some),
|
"*" => return mul(x, y).map(Into::into).map(Some),
|
||||||
"/" => return div(x, y).map(Into::<Dynamic>::into).map(Some),
|
"/" => return div(x, y).map(Into::into).map(Some),
|
||||||
"%" => return modulo(x, y).map(Into::<Dynamic>::into).map(Some),
|
"%" => return modulo(x, y).map(Into::into).map(Some),
|
||||||
"~" => return pow_i_i(x, y).map(Into::<Dynamic>::into).map(Some),
|
"~" => return pow_i_i(x, y).map(Into::into).map(Some),
|
||||||
">>" => return shr(x, y).map(Into::<Dynamic>::into).map(Some),
|
">>" => return shr(x, y).map(Into::into).map(Some),
|
||||||
"<<" => return shl(x, y).map(Into::<Dynamic>::into).map(Some),
|
"<<" => return shl(x, y).map(Into::into).map(Some),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2283,9 +2283,9 @@ fn run_builtin_binary_op(
|
|||||||
"*" => return Ok(Some((x * y).into())),
|
"*" => return Ok(Some((x * y).into())),
|
||||||
"/" => return Ok(Some((x / y).into())),
|
"/" => return Ok(Some((x / y).into())),
|
||||||
"%" => return Ok(Some((x % y).into())),
|
"%" => return Ok(Some((x % y).into())),
|
||||||
"~" => return pow_i_i_u(x, y).map(Into::<Dynamic>::into).map(Some),
|
"~" => return pow_i_i_u(x, y).map(Into::into).map(Some),
|
||||||
">>" => return shr_u(x, y).map(Into::<Dynamic>::into).map(Some),
|
">>" => return shr_u(x, y).map(Into::into).map(Some),
|
||||||
"<<" => return shl_u(x, y).map(Into::<Dynamic>::into).map(Some),
|
"<<" => return shl_u(x, y).map(Into::into).map(Some),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2359,7 +2359,7 @@ fn run_builtin_binary_op(
|
|||||||
"*" => return Ok(Some((x * y).into())),
|
"*" => return Ok(Some((x * y).into())),
|
||||||
"/" => return Ok(Some((x / y).into())),
|
"/" => return Ok(Some((x / y).into())),
|
||||||
"%" => return Ok(Some((x % y).into())),
|
"%" => return Ok(Some((x % y).into())),
|
||||||
"~" => return pow_f_f(x, y).map(Into::<Dynamic>::into).map(Some),
|
"~" => return pow_f_f(x, y).map(Into::into).map(Some),
|
||||||
"==" => return Ok(Some((x == y).into())),
|
"==" => return Ok(Some((x == y).into())),
|
||||||
"!=" => return Ok(Some((x != y).into())),
|
"!=" => return Ok(Some((x != y).into())),
|
||||||
">" => return Ok(Some((x > y).into())),
|
">" => return Ok(Some((x > y).into())),
|
||||||
|
@ -15,6 +15,7 @@ use crate::stdlib::{
|
|||||||
fmt::Display,
|
fmt::Display,
|
||||||
format,
|
format,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn prepend<T: Display>(x: T, y: ImmutableString) -> FuncReturn<ImmutableString> {
|
fn prepend<T: Display>(x: T, y: ImmutableString) -> FuncReturn<ImmutableString> {
|
||||||
@ -290,4 +291,12 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
|||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Register string iterator
|
||||||
|
lib.set_iter(
|
||||||
|
TypeId::of::<ImmutableString>(),
|
||||||
|
|arr| Box::new(
|
||||||
|
arr.cast::<ImmutableString>().chars().collect::<Vec<_>>().into_iter().map(Into::into)
|
||||||
|
) as Box<dyn Iterator<Item = Dynamic>>,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
20
tests/for.rs
20
tests/for.rs
@ -30,6 +30,26 @@ fn test_for_array() -> Result<(), Box<EvalAltResult>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_for_string() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
let engine = Engine::new();
|
||||||
|
|
||||||
|
let script = r#"
|
||||||
|
let s = "hello";
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
for ch in s {
|
||||||
|
sum += ch.to_int();
|
||||||
|
}
|
||||||
|
|
||||||
|
sum
|
||||||
|
"#;
|
||||||
|
|
||||||
|
assert_eq!(engine.eval::<INT>(script)?, 532);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user