Arrays
Un array es una colección de elementos del mismo tipo. Puedes crear y utilizar métodos de array mediante el uso del rasgo ArrayTrait
de la libreria principal.
An important thing to note is that arrays have limited modification options. Arrays are, in fact, queues whose values can't be modified. This has to do with the fact that once a memory slot is written to, it cannot be overwritten, but only read from it. You can only append items to the end of an array and remove items from the front.
Crear un Array
Creating an array is done with the ArrayTrait::new()
call. Here's an example of creating an array and appending 3 elements to it:
fn main() {
let mut a = ArrayTrait::new();
a.append(0);
a.append(1);
a.append(2);
}
Cuando sea necesario, puedes pasar el tipo esperado de elementos dentro del array al instanciarlo de esta manera, o definir explícitamente el tipo del mismo.
let mut arr = ArrayTrait::<u128>::new();
let mut arr:Array<u128> = ArrayTrait::new();
Actualizar un Array
Añadir Elementos
Para añadir un elemento al final de un array, puedes utilizar el método append()
:
fn main() {
let mut a = ArrayTrait::new();
a.append(0);
a.append(1);
a.append(2);
}
Eliminar Elementos
You can only remove elements from the front of an array by using the pop_front()
method. This method returns an Option
that can be unwrapped, containing the removed element, or Option::None
if the array is empty.
fn main() {
let mut a = ArrayTrait::new();
a.append(10);
a.append(1);
a.append(2);
let first_value = a.pop_front().unwrap();
println!("The first value is {}", first_value);
}
The above code will print The first value is 10
as we remove the first element that was added.
En Cairo, la memoria es inmutable, lo que significa que no es posible modificar los elementos de un array una vez que han sido añadidos. Sólo se pueden añadir elementos al final de un array y eliminar elementos de la parte frontal de un array. Estas operaciones no requieren mutación de memoria, ya que implican actualizar punteros en lugar de modificar directamente las celdas de memoria.
Lectura de Elementos en un Array
Para acceder a los elementos de un array, puedes utilizar los métodos get()
o at()
que devuelven diferentes tipos. Utilizar arr.at(index)
es equivalente a utilizar el operador de subíndice arr[index]
.
get()
Method
The get
function returns an Option<Box<@T>>
, which means it returns an option to a Box type (Cairo's smart-pointer type) containing a snapshot to the element at the specified index if that element exists in the array. If the element doesn't exist, get
returns None
. This method is useful when you expect to access indices that may not be within the array's bounds and want to handle such cases gracefully without panics. Snapshots will be explained in more detail in the "References and Snapshots" chapter.
He aquí un ejemplo con el método get()
:
fn main() -> u128 {
let mut arr = ArrayTrait::<u128>::new();
arr.append(100);
let index_to_access =
1; // Change this value to see different results, what would happen if the index doesn't exist?
match arr.get(index_to_access) {
Option::Some(x) => {
*x
.unbox() // Don't worry about * for now, if you are curious see Chapter 4.2 #desnap operator
// It basically means "transform what get(idx) returned into a real value"
},
Option::None => { panic!("out of bounds") },
}
}
at()
Method
The at
function, and its equivalent the subscripting operator, on the other hand, directly return a snapshot to the element at the specified index using the unbox()
operator to extract the value stored in a box. If the index is out of bounds, a panic error occurs. You should only use at
when you want the program to panic if the provided index is out of the array's bounds, which can prevent unexpected behavior.
fn main() {
let mut a = ArrayTrait::new();
a.append(0);
a.append(1);
// using the `at()` method
let first = *a.at(0);
assert!(first == 0);
// using the subscripting operator
let second = *a[1];
assert!(second == 1);
}
En este ejemplo, la variable llamada first
obtendrá el valor 0
porque es el valor del índice 0
del array. La variable llamada second
obtendrá el valor 1
del índice 1
del array.
En resumen, usa at
cuando quieras que el programa entre en pánico ante intentos de acceso fuera de los límites, y usa get
cuando prefieras manejar estos casos con gracia sin entrar en pánico.
Size-related Methods
To determine the number of elements in an array, use the len()
method. The return value is of type usize
.
Si quieres comprobar si un array está vacío o no, puedes utilizar el método is_empty()
, que devuelve true
si el array está vacío y false
en caso contrario.
array!
Macro
A veces, necesitamos crear arrays con valores que ya se conocen en tiempo de compilación. La forma básica de hacerlo es redundante. Primero declararías el array y luego añadirías cada valor uno por uno. array!
es una forma más sencilla de realizar esta tarea al combinar los dos pasos. En tiempo de compilación, el compilador expandirá la macro para generar el código que añade los elementos de forma secuencial
Sin array!
:
let mut arr = ArrayTrait::new();
arr.append(1);
arr.append(2);
arr.append(3);
arr.append(4);
arr.append(5);
Con array!
:
let arr = array![1, 2, 3, 4, 5];
Storing Multiple Types with Enums
If you want to store elements of different types in an array, you can use an Enum
to define a custom data type that can hold multiple types. Enums will be explained in more detail in the "Enums and Pattern Matching" chapter.
#[derive(Copy, Drop)]
enum Data {
Integer: u128,
Felt: felt252,
Tuple: (u32, u32),
}
fn main() {
let mut messages: Array<Data> = array![];
messages.append(Data::Integer(100));
messages.append(Data::Felt('hello world'));
messages.append(Data::Tuple((10, 30)));
}
Span
Span
is a struct that represents a snapshot of an Array
. It is designed to provide safe and controlled access to the elements of an array without modifying the original array. Span is particularly useful for ensuring data integrity and avoiding borrowing issues when passing arrays between functions or when performing read-only operations, as introduced in "References and Snapshots".
All methods provided by Array
can also be used with Span
, except for the append()
method.
Turning an Array into Span
Para crear un Span
de un Array
, llama al método span()
:
fn main() {
let mut array: Array<u8> = ArrayTrait::new();
array.span();
}