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.
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? :-)
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
:
That’s all it takes!
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.