From 8128c0cf241d73f757a14987eed5ad19c535a7fd Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 25 Feb 2020 16:23:59 +0800 Subject: [PATCH] Add pad and truncate array functions. --- README.md | 23 ++++++++++++++++++++--- src/engine.rs | 26 +++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 495bcf46..75532d80 100644 --- a/README.md +++ b/README.md @@ -444,8 +444,15 @@ fn decide(yes_no: bool) -> Dynamic { ## Arrays You can create arrays of values, and then access them with numeric indices. -The functions `push`, `pop` and `shift` can be used to insert and remove elements -to/from arrays. + +The following standard functions operate on arrays: + +* `push` - inserts an element at the end +* `pop` - removes the last element and returns it (() if empty) +* `shift` - removes the first element and returns it (() if empty) +* `len` - returns the number of elements +* `pad` - pads the array with an element until a specified length +* `truncate` - cuts off the array at exactly a specified length (discarding all subsequent elements) ```rust let y = [1, 2, 3]; // 3 elements @@ -463,9 +470,19 @@ first == 1; let last = y.pop(); // remove the last element, 3 elements remaining last == 5; + +print(y.len()); // prints 3 + +y.pad(10, "hello"); // pad the array up to 10 elements + +print(y.len()); // prints 10 + +y.truncate(5); // truncate the array to 5 elements + +print(y.len()); // prints 5 ``` -`push` is only defined for standard built-in types. If you want to use `push` with +`push` and `pad` are only defined for standard built-in types. If you want to use them with your own custom type, you need to define a specific override: ```rust diff --git a/src/engine.rs b/src/engine.rs index cc18c4e9..f024d108 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -951,6 +951,14 @@ impl Engine { ) } + macro_rules! reg_func3 { + ($engine:expr, $x:expr, $op:expr, $v:ty, $w:ty, $r:ty, $( $y:ty ),*) => ( + $( + $engine.register_fn($x, $op as fn(x: $v, y: $w, z: $y)->$r); + )* + ) + } + fn add(x: T, y: T) -> ::Output { x + y } @@ -1095,13 +1103,24 @@ impl Engine { reg_func1!(engine, "debug", print_debug, String, Array, ()); // Register array functions - fn push(list: &mut Array, item: T) { + fn push(list: &mut Array, item: T) { list.push(Box::new(item)); } + fn pad(list: &mut Array, len: i64, item: T) { + if len >= 0 { + while list.len() < len as usize { + push(list, item.clone()); + } + } + } reg_func2x!(engine, "push", push, &mut Array, (), i32, i64, u32, u64); reg_func2x!(engine, "push", push, &mut Array, (), f32, f64, bool); reg_func2x!(engine, "push", push, &mut Array, (), String, Array, ()); + reg_func3!(engine, "pad", pad, &mut Array, i64, (), i32, i64); + reg_func3!(engine, "pad", pad, &mut Array, i64, (), u32, u64); + reg_func3!(engine, "pad", pad, &mut Array, i64, (), f32, f64, bool); + reg_func3!(engine, "pad", pad, &mut Array, i64, (), String, Array, ()); engine.register_dynamic_fn("pop", |list: &mut Array| list.pop().unwrap_or(Box::new(()))); engine.register_dynamic_fn("shift", |list: &mut Array| { @@ -1114,6 +1133,11 @@ impl Engine { engine.register_fn("len", |list: &mut Array| -> i64 { list.len().try_into().unwrap() }); + engine.register_fn("truncate", |list: &mut Array, len: i64| { + if len >= 0 { + list.truncate(len as usize); + } + }); // Register string concatenate functions fn prepend(x: T, y: String) -> String {