mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Add sum and product to arrays (#966)
This commit is contained in:
parent
12129f0170
commit
efad1e71fa
@ -630,6 +630,20 @@ Folds all items into a single value using an accumulator function.
|
||||
and one for an item.
|
||||
- returns: any
|
||||
|
||||
### sum()
|
||||
Sums all items (works for any types that can be added).
|
||||
|
||||
- default: any (named)
|
||||
If set and the array is empty, sum will return this.
|
||||
- returns: any
|
||||
|
||||
### product()
|
||||
Calculates the product all items (works for any types that can be multiplied)
|
||||
|
||||
- default: any (named)
|
||||
If set and the array is empty, sum will return this.
|
||||
- returns: any
|
||||
|
||||
### any()
|
||||
Whether the given function returns `{true}` for any item in the array.
|
||||
|
||||
|
@ -24,6 +24,7 @@ macro_rules! __array {
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::__array as array;
|
||||
use crate::eval::ops::{add, mul};
|
||||
#[doc(hidden)]
|
||||
pub use ecow::eco_vec;
|
||||
|
||||
@ -199,6 +200,40 @@ impl Array {
|
||||
Ok(acc)
|
||||
}
|
||||
|
||||
/// Calculates the sum of the array's items
|
||||
pub fn sum(&self, default: Option<Value>, span: Span) -> SourceResult<Value> {
|
||||
let mut acc = self
|
||||
.first()
|
||||
.map(|x| x.clone())
|
||||
.or_else(|_| {
|
||||
default.ok_or_else(|| {
|
||||
eco_format!("cannot calculate sum of empty array with no default")
|
||||
})
|
||||
})
|
||||
.at(span)?;
|
||||
for i in self.iter().skip(1) {
|
||||
acc = add(acc, i.clone()).at(span)?;
|
||||
}
|
||||
Ok(acc)
|
||||
}
|
||||
|
||||
/// Calculates the product of the array's items
|
||||
pub fn product(&self, default: Option<Value>, span: Span) -> SourceResult<Value> {
|
||||
let mut acc = self
|
||||
.first()
|
||||
.map(|x| x.clone())
|
||||
.or_else(|_| {
|
||||
default.ok_or_else(|| {
|
||||
eco_format!("cannot calculate product of empty array with no default")
|
||||
})
|
||||
})
|
||||
.at(span)?;
|
||||
for i in self.iter().skip(1) {
|
||||
acc = mul(acc, i.clone()).at(span)?;
|
||||
}
|
||||
Ok(acc)
|
||||
}
|
||||
|
||||
/// Whether any item matches.
|
||||
pub fn any(&self, vm: &mut Vm, func: Func) -> SourceResult<bool> {
|
||||
for item in self.iter() {
|
||||
|
@ -105,6 +105,8 @@ pub fn call(
|
||||
"fold" => {
|
||||
array.fold(vm, args.expect("initial value")?, args.expect("function")?)?
|
||||
}
|
||||
"sum" => array.sum(args.named("default")?, span)?,
|
||||
"product" => array.product(args.named("default")?, span)?,
|
||||
"any" => Value::Bool(array.any(vm, args.expect("function")?)?),
|
||||
"all" => Value::Bool(array.all(vm, args.expect("function")?)?),
|
||||
"flatten" => Value::Array(array.flatten()),
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 8.2 KiB |
@ -166,6 +166,27 @@
|
||||
// Error: 20-22 unexpected argument
|
||||
#(1, 2, 3).fold(0, () => none)
|
||||
|
||||
---
|
||||
// Test the `sum` method.
|
||||
#test(().sum(default: 0), 0)
|
||||
#test(().sum(default: []), [])
|
||||
#test((1, 2, 3).sum(), 6)
|
||||
|
||||
---
|
||||
// Error: 2-10 cannot calculate sum of empty array with no default
|
||||
#().sum()
|
||||
|
||||
---
|
||||
// Test the `product` method.
|
||||
#test(().product(default: 0), 0)
|
||||
#test(().product(default: []), [])
|
||||
#test(([ab], 3).product(), [ab]*3)
|
||||
#test((1, 2, 3).product(), 6)
|
||||
|
||||
---
|
||||
// Error: 2-14 cannot calculate product of empty array with no default
|
||||
#().product()
|
||||
|
||||
---
|
||||
// Test the `rev` method.
|
||||
#test(range(3).rev(), (2, 1, 0))
|
||||
|
Loading…
x
Reference in New Issue
Block a user