diff --git a/ndc_lib/src/stdlib/sequence.rs b/ndc_lib/src/stdlib/sequence.rs index 73e56dcd..85961363 100644 --- a/ndc_lib/src/stdlib/sequence.rs +++ b/ndc_lib/src/stdlib/sequence.rs @@ -486,7 +486,7 @@ mod inner { ) } - //// Returns al prefixes of a sequence, each as a list. + /// Returns al prefixes of a sequence, each as a list. pub fn prefixes(seq: &mut Sequence) -> Value { // Special case for string which is more efficient and doesn't produce lists of characters if let Sequence::String(string) = &seq { @@ -676,6 +676,23 @@ mod inner { Ok(Value::list(out)) } + + /// Split the input sequence into evenly sized chunks. If the input length of the sequence + /// is not dividable by the chunk_size the last chunk will contain fewer elements. + pub fn chunks(seq: &mut Sequence, chunk_size: usize) -> anyhow::Result { + if chunk_size == 0 { + return Err(anyhow!("chunk size must be non-zero")); + } + + let iter = mut_seq_to_iterator(seq); + + Ok(Value::list( + iter.chunks(chunk_size) + .into_iter() + .map(|chunk| Value::list(chunk.collect_vec())) + .collect_vec(), + )) + } } fn fold_iterator( diff --git a/ndc_lib/src/stdlib/string.rs b/ndc_lib/src/stdlib/string.rs index 6a2f9563..a555c7cd 100644 --- a/ndc_lib/src/stdlib/string.rs +++ b/ndc_lib/src/stdlib/string.rs @@ -31,6 +31,11 @@ mod inner { format!("{left}{right}") } + /// Returns the provided value as a string + pub fn string(value: &Value) -> String { + format!("{value}") + } + /// Returns the Unicode code point of a 1-length string. pub fn ord(string: &str) -> anyhow::Result { if string.chars().count() == 1 {