Skip to content

Instantly share code, notes, and snippets.

@horsefacts
Created September 28, 2022 15:42
Show Gist options
  • Save horsefacts/6a228381c78c08b73cca34919ee14d6f to your computer and use it in GitHub Desktop.
Save horsefacts/6a228381c78c08b73cca34919ee14d6f to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
library Iterators {
// Function types:
// https://docs.soliditylang.org/en/latest/types.html#function-types
function map(uint256[] memory input, function (uint256) internal pure returns (uint256) f)
internal
pure
returns (uint256[] memory)
{
uint256[] memory output = new uint256[](input.length);
for (uint256 i; i < input.length;) {
output[i] = f(input[i]);
unchecked {
++i;
}
}
return output;
}
function filter(uint256[] memory input, function (uint256) internal pure returns (bool) f)
internal
pure
returns (uint256[] memory)
{
uint256 idx;
uint256[] memory filtered = new uint256[](input.length);
for (uint256 i; i < input.length;) {
if (f(input[i])) {
++idx;
filtered[idx] = input[i];
}
unchecked {
++i;
}
}
uint256[] memory output = new uint256[](idx+1);
for (uint256 i; i < output.length;) {
output[i] = filtered[i];
unchecked { ++i; }
}
return output;
}
function reduce(uint256[] memory input, function (uint256,uint256) internal pure returns (uint256) f)
internal
pure
returns (uint256)
{
uint256 acc;
for (uint256 i; i < input.length;) {
acc = f(acc, input[i]);
unchecked {
++i;
}
}
return acc;
}
}
// Free functions:
// https://docs.soliditylang.org/en/latest/contracts.html#functions
function addOne(uint256 n) pure returns (uint256) {
return n + 1;
}
function isOdd(uint256 n) pure returns (bool) {
return n % 2 == 1;
}
function add(uint256 acc, uint256 n) pure returns (uint256) {
return acc + n;
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Iterators, addOne, isOdd, add} from "../src/Iterators.sol";
import "forge-std/Test.sol";
contract IteratorsTest is Test {
// Using For:
// https://docs.soliditylang.org/en/latest/contracts.html#using-for
using Iterators for uint256[];
uint256[] input;
function setUp() public {
// Create a uint256 array containing 0..10
input = new uint256[](10);
for (uint256 i; i < input.length; i++) {
input[i] = i;
}
}
function test_chained_functions() public {
uint256 sum = input.map(addOne).filter(isOdd).reduce(add);
assertEq(sum, 25);
}
function test_map() public {
uint256[] memory mapped = Iterators.map(input, addOne);
assertEq(mapped[0], 1);
assertEq(mapped[1], 2);
assertEq(mapped[2], 3);
assertEq(mapped[3], 4);
assertEq(mapped[4], 5);
assertEq(mapped[5], 6);
assertEq(mapped[6], 7);
assertEq(mapped[7], 8);
assertEq(mapped[8], 9);
assertEq(mapped[9], 10);
}
function test_filter() public {
uint256[] memory filtered = Iterators.filter(input, isOdd);
assertEq(filtered.length, 6);
assertEq(filtered[0], 0);
assertEq(filtered[1], 1);
assertEq(filtered[2], 3);
assertEq(filtered[3], 5);
assertEq(filtered[4], 7);
assertEq(filtered[5], 9);
}
function test_reduce() public {
uint256 reduced = Iterators.reduce(input, add);
assertEq(reduced, 45);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment