Array stream library for Cairo

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, 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
foreach implementation with custom implicit argument

That’s all it takes!

Conclusion

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:

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.

Subscribe to Only Dust
Receive the latest updates directly to your inbox.
Verification
This entry has been permanently stored onchain and signed by its creator.