# Array stream library for Cairo

By [Only Dust](https://paragraph.com/@only-dust) · 2022-05-20

---

The lack of `for` loops in Cairo can be a bit disturbing for new comers. Even for experienced developers, having to write recursive functions every time you want to do something with an array can be time-consuming.

This is why we at OnlyDust developed [Cairo Streams](https://github.com/onlydustxyz/cairo-streams), an array stream library that can save you a lot of time and make your code easier to read and understand.

This library provides high-level functions such as `foreach`, `filter`, `map` and `reduce`.

Here is how it looks like:

    let (local array : felt*) = alloc()
    assert array[0] = 1
    assert array[1] = 1
    assert array[2] = 1
    assert array[3] = 7
    
    stream.foreach(do_something, 4, array)
    

Where `do_something` is a function you provide (it can of course be named differently):

    func do_something{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(index : felt, element : felt*):
        ...
        # do whatever you want with the array element 'element'
        # as 'element' is a pointer, you can use it to initialize the array
        ...
        return ()
    end
    

As you can see, this code is **faster to write** and **easier to read** compared to the implementation of a recursive function.

### What about arrays of structs?

We already wrote a variant for each method that works with arrays of structs.

The `foreach_struct` is just as simple to use as the classical `foreach`. All you have to do is to pass the size of the struct as a parameter.

Assuming you have a struct Foo:

    struct Foo:
        member x : felt
        member y : felt
    end
    

You can write:

    let (local array : Foo*) = alloc()
    assert array[0] = Foo(1, 10)
    assert array[1] = Foo(1, 10)
    assert array[2] = Foo(2, 20)
    assert array[3] = Foo(7, 70)
    
    stream.foreach_struct(do_something, 4, array, Foo.SIZE)
    

Where `do_something` looks like this:

    func do_something{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(element : Foo*):
        ...
        # do whatever you want with 'element'
        ...
        return ()
    end
    

Easy, right? :-)

Implicit arguments
------------------

The library provides default implementations for `foreach`, `filter`, `map` and `reduce` that expect those common implicit arguments: `{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}`.

You may want to use different implicit arguments, maybe even custom ones, or no implicit argument at all.

In such case, you can write your own implementations in a few lines thanks to the functions provided in the `generic` namespace.

Here is an example with a custom implicit parameter `my_custom_param`:

![foreach implementation with custom implicit argument](https://storage.googleapis.com/papyrus_images/8989cd57809a13ddd034548c546580f6eb9c1019b60f315f8787ef05cbe2c8c1.png)

foreach implementation with custom implicit argument

That’s all it takes!

Conclusion
----------

[Cairo Streams](https://github.com/onlydustxyz/cairo-streams) will save your time and make your code easier to read by providing high-level functions to perform various operations on arrays.

It can be found on GitHub here:

[https://github.com/onlydustxyz/cairo-streams](https://github.com/onlydustxyz/cairo-streams)

It is still in early development but we expect to improve it quickly.

It is thoroughly tested, but if you encounter any problem please open [an issue on our GitHub repo](https://github.com/onlydustxyz/cairo-streams/issues).

---

*Originally published on [Only Dust](https://paragraph.com/@only-dust/array-stream-library-for-cairo)*
