Skip to content

Commit

Permalink
Add array.filter
Browse files Browse the repository at this point in the history
  • Loading branch information
danhper committed Aug 7, 2024
1 parent f9cb78c commit df5495c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

* Decode logs returned by `Transaction.getReceipt()` when available in ABI
* Add support for array concatenation
* Add `array.filter` function

### Other changes

Expand Down
11 changes: 11 additions & 0 deletions docs/src/builtin_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ Applies the function `f` to each element of the array and returns a new array wi
[2, 4, 6]
```

### `array.filter(function p) -> array`

Applies the predicate `p` to each element and only includes the elements for which the predicate returns `true`.

```javascript
>> function isEven(x) { return x % 2 == 0; }
>> [1, 2, 3, 4, 5].filter(isEven)
[2, 4]
```

### `array.concat(array other) -> array`

Concatenates two arrays.
Expand All @@ -66,6 +76,7 @@ Concatenates two arrays.
[1, 2, 3, 4]
```


## `tuple` methods

### `tuple[uint256 index] -> any`
Expand Down
30 changes: 30 additions & 0 deletions src/interpreter/builtins/iterable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@ fn map<'a>(
.boxed()
}

fn filter<'a>(
env: &'a mut Env,
receiver: &'a Value,
args: &'a [Value],
) -> BoxFuture<'a, Result<Value>> {
async move {
let mut values = vec![];
for v in receiver.get_items()? {
match args.first() {
Some(Value::Func(func)) => match func.execute(env, &[v.clone()]).await? {
Value::Bool(true) => values.push(v),
Value::Bool(false) => continue,
_ => bail!("filter function must return a boolean"),
},
_ => bail!("filter function expects a function as an argument"),
};
}
match receiver.get_type() {
Type::Array(t) => Ok(Value::Array(values, t.clone())),
ty => bail!("cannot map to type {}", ty),
}
}
.boxed()
}

pub fn iter_len(_env: &Env, arg: &Value) -> Result<Value> {
arg.len().map(Into::into)
}
Expand All @@ -43,5 +68,10 @@ lazy_static! {
map,
vec![vec![FunctionParam::new("f", Type::Function)]]
);
pub static ref ITER_FILTER: Arc<dyn FunctionDef> = AsyncMethod::arc(
"filter",
filter,
vec![vec![FunctionParam::new("p", Type::Function)]]
);
pub static ref ITER_LEN: Arc<dyn FunctionDef> = SyncProperty::arc("length", iter_len);
}
1 change: 1 addition & 0 deletions src/interpreter/builtins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ lazy_static! {
let mut array_methods = HashMap::new();
array_methods.insert("length".to_string(), ITER_LEN.clone());
array_methods.insert("map".to_string(), iterable::ITER_MAP.clone());
array_methods.insert("filter".to_string(), iterable::ITER_FILTER.clone());
array_methods.insert("concat".to_string(), concat::CONCAT.clone());
array_methods.insert("format".to_string(), format::NON_NUM_FORMAT.clone());
m.insert(NonParametricType::Array, array_methods);
Expand Down

0 comments on commit df5495c

Please sign in to comment.