Skip to main content

Collection types

Rell supports the following collection types:

  • list<T> - An ordered list that allows duplicate elements.
  • set<T> - An unordered set that does not contain duplicate elements.
  • map<K,V> - A key-value map.

Properties of collection types

  • Mutable: You can dynamically add or remove elements.
  • Map key or set element: Only non-mutable types can be used as map keys or set elements.

Mutable collection types

  • Collection types (list, set, map): Always mutable.
  • Nullable type: Only if the underlying type is mutable.
  • Struct type: If the struct has a mutable field or a field of a mutable type.
  • Tuple: If an element type is mutable.

Creating collections

function foo() {
// list
val l1 = [1, 2, 3, 4, 5, 1];
val l2 = list < integer > ();

// set
val s = set < integer > ();

// map
val m1 = ['Bob': 123, 'Alice': 456];
val m2 = map < text, integer > ();
}

list<T>

A list is an ordered collection type that allows duplicate elements.

Constructors

  • list<T>() - Creates a new empty list.

  • list<T>(list<T>) - Creates a copy of the given list (a list of a subtype is also acceptable).

  • list<T>(set<T>) - Creates a copy of the given set (a set of a subtype is also acceptable).

Functions

FunctionDescription
.add(T): booleanAdds an element to the end of the list. Always returns true.
.add(pos: integer, T): booleanInserts an element at a given position in the list. Always returns true.
.add_all(list<T>): booleanAdds all elements from the given list to the end of the list.
.add_all(set<T>): booleanAdds all elements from the given set to the end of the list.
.add_all(pos: integer, list<T>): booleanInserts all elements from the given list at the specified position in the list.
.add_all(pos: integer, set<T>): booleanInserts all elements from the given set at the specified position in the list.
.clear()Removes all elements from the list.
.contains(T): booleanChecks if the list contains the specified element.
.contains_all(list<T>): booleanChecks if the list contains all elements from the given list.
.contains_all(set<T>): booleanChecks if the list contains all elements from the given set.
.empty(): booleanReturns true if the list is empty, otherwise returns false.
.index_of(T): integerReturns the position of the first occurrence of the element in the list. Returns -1 if the element isn't found.
.remove(T): booleanRemoves the first occurrence of the specified element from the list. Returns true if found.
.remove_all(list<T>): booleanRemoves all elements from the list that are present in the given list.
.remove_all(set<T>): booleanRemoves all elements from the list that are present in the given set.
.remove_at(pos: integer): TRemoves the element at the given position in the list and returns it.
.repeat(n: integer): list<T>Returns a new list, which is the old list repeated "n" times. Always creates a new list (even if n = 1).
.size(): integerReturns the number of elements in the list.
.reverse()Reverses the order of elements in the list in place. Returns nothing.
.reversed(): list<T>Returns a reversed copy of the list. Always creates a new list (even if the old list is empty or has one element).
._sort()Sorts the list in ascending order. Returns nothing.
.sorted(): list<T>Returns a sorted copy of the list in ascending order.
.to_text(): textReturns a text representation of the list, e.g., '[1, 2, 3, 4, 5]'.
.sub(start: integer[, end: integer]): list<T>Returns a sub-list (start-inclusive, end-exclusive) from the list.

Special operators

  • [] - Accesses or modifies an element at a specified index in the list.
  • in - Checks if a specified value exists in the list, returning true if it does.

Example:

function example_list() {
// Creating a list of transactions
val transactions = list<Transaction>();

// Adding transactions to the list
transactions.add(Transaction(id = 1, amount = 100, sender = "Alice", recipient = "Bob"));
transactions.add(Transaction(id = 2, amount = 200, sender = "Bob", recipient = "Charlie"));
transactions.add(Transaction(id = 3, amount = 150, sender = "Charlie", recipient = "Alice"));

// Accessing a transaction by index
val firstTransaction = transactions[0];
print("First transaction amount: ${firstTransaction.amount}");

// Modifying a transaction at a specific index
transactions[1] = Transaction(id = 2, amount = 250, sender = "Bob", recipient = "Charlie");

// Using contains with a custom equality check
val searchTransaction = Transaction(id = 3, amount = 150, sender = "Charlie", recipient = "Alice");
if (searchTransaction in transactions) {
print("Transaction found in the list");
}

// Using sub to get a portion of the list
val subList = transactions.sub(0, 2);
print("Sub-list size: ${subList.size()}");

// Creating a reversed copy of the list
val reversedList = transactions.reversed();

// Converting the list to text
print("Transactions: ${transactions.to_text()}");
}

set<T>

An unordered collection type that does not allow duplicate elements.

struct Address {
value: text;
}

function example_set() {
// Creating a set of unique addresses
val uniqueAddresses = set<Address>();

// Adding addresses to the set
uniqueAddresses.add(Address("0xabc123"));
uniqueAddresses.add(Address("0xdef456"));
uniqueAddresses.add(Address("0xabc123")); // This won't be added as it's a duplicate

// Checking if an address exists in the set
if (Address("0xabc123") in uniqueAddresses) {
print("Address 0xabc123 is in the set");
}

// Removing an address from the set
uniqueAddresses.remove(Address("0xabc123"));

// Adding multiple addresses at once
val newAddresses = [Address("0xghi789"), Address("0xjkl012")];
uniqueAddresses.add_all(newAddresses);

// Printing the set
print("Unique addresses: ${uniqueAddresses.to_text()}");
}

Constructors

  • set<T>() - Creates a new empty set.

  • set<T>(set<T>) - Creates a copy of the given set (a set of a subtype is also acceptable).

  • set<T>(list<T>) - Creates a copy of the given list (with duplicates removed).

Functions

FunctionDescription
.add(T): booleanIf the element isn't in the set, adds it and returns true.
.add_all(list<T>): booleanAdds all elements from the given list to the set. Returns true if at least one element was added.
.add_all(set<T>): booleanAdds all elements from the given set to the set. Returns true if at least one element was added.
.clear()Removes all elements from the set.
.contains(T): booleanChecks if the set contains the specified element.
.contains_all(list<T>): booleanChecks if the set contains all elements from the given list.
.contains_all(set<T>): booleanChecks if the set contains all elements from the given set.
.empty(): booleanReturns true if the set is empty, otherwise returns false.
.remove(T): booleanRemoves the specified element from the set. Returns true if the element was found and removed.
.remove_all(list<T>): booleanRemoves all elements from the set that are present in the given list. Returns true if at least one element was removed.
.remove_all(set<T>): booleanRemoves all elements from the set that are present in the given set. Returns true if at least one element was removed.
.size(): integerReturns the number of elements in the set.
.sorted(): list<T>Returns a sorted copy of the set as a list.
.to_text(): textReturns a text representation of the set, e.g., '[1, 2, 3, 4, 5]'.

Special operators

  • in - Checks if a specified value exists in the set, returning true if it does.

Example:

struct Address {
value: text;
}

function example_set() {
// Creating a set of unique addresses
val uniqueAddresses = set<Address>();

// Adding addresses to the set
uniqueAddresses.add(Address("0xabc123"));
uniqueAddresses.add(Address("0xdef456"));
uniqueAddresses.add(Address("0xabc123")); // This won't be added as it's a duplicate

// Using 'in' operator to check if an address exists in the set
if (Address("0xabc123") in uniqueAddresses) { // 'in' operator
print("Address 0xabc123 is in the set");
}

// Additional examples using the 'in' operator
val addressesToCheck = [
Address("0xabc123"),
Address("0xdef456"),
Address("0xghi789"),
Address("0xjkl012")
];

for (addr in addressesToCheck) {
if (addr in uniqueAddresses) { // 'in' operator
print("Address ${addr.value} is in the set");
} else {
print("Address ${addr.value} is not in the set");
}
}

// Removing an address from the set
uniqueAddresses.remove(Address("0xabc123"));

// Adding multiple addresses at once
val newAddresses = [Address("0xghi789"), Address("0xjkl012")];
uniqueAddresses.add_all(newAddresses);

// Printing the set
print("Unique addresses: ${uniqueAddresses.to_text()}");
}

map<K,V>

A key-value pair collection type.

struct Balance {
amount: integer;
lastUpdated: timestamp;
}

function example_map() {
// Creating a map of blockchain addresses and their balances
val balances = map<text, Balance>();

// Adding balances to the map
balances["0xabc123"] = Balance(amount = 1000, lastUpdated = 1723472827);
balances["0xdef456"] = Balance(amount = 2000, lastUpdated = 1723472900);

// Accessing a balance by address
val aliceBalance = balances["0xabc123"];
print("Alice's balance: ${aliceBalance.amount}, Last updated: ${aliceBalance.lastUpdated}");
}

Constructors

  • map<K,V>() - Creates a new empty map.
  • map<K,V>(iterable<(K,V)>) - Creates a new map from list, set, or map key-value pairs.

Functions

FunctionDescription
.clear()Removes all key-value pairs from the map.
.contains(K): booleanChecks if the map contains the specified key.
.empty(): booleanReturns true if the map is empty, otherwise returns false.
.get(K): VGet the value associated with the specified key.
.get_or_null(key: K): V?Returns null if the key isn't in the map; otherwise returns the associated value.
.get_or_default(key: K, default_value: V2): V2Returns a default value if the key isn't in the map; otherwise returns the associated value.
.remove_or_null(key: K): V?Removes the specified key from the map. Returns null if the key isn't in the map.
.put(K, V)Adds/replaces a key-value pair in the map.
.keys(): set<K>Returns a copy of keys in the map.
.put_all(map<K, V>)Adds/replaces all key-value pairs from the given map to the map.
.remove(K): VRemoves the key-value pair associated with the specified key from the map.
.size(): integerReturns the number of key-value pairs in the map.
.to_text(): textReturns a text representation of the map, e.g., '{x=123, y=456}'.
.values(): list<V>Returns a copy of values in the map.

Special operators

  • [] - Accesses or modifies a value by key.
  • in - Checks if a specified key exists in the map, returning true if it does.

Example:

struct Balance {
mutable amount: integer;
lastUpdated: timestamp;
}

function example_map() {
/// Creating a map of blockchain addresses and their balances
val balances = map<text, Balance>();

// Using [] operator to add and modify balances
balances["0xabc123"] = Balance(amount = 1000, lastUpdated = 1723472827);
balances["0xdef456"] = Balance(amount = 2000, lastUpdated = 1723472937);
balances["0xghi789"] = Balance(amount = 3000, lastUpdated = 1723473427);

// Using [] operator to access balances
print("Alice's balance: ${balances[0xabc123].amount}");
print("Bob's balance: ${balances[0xdef456].amount}");

// Using [] operator to modify an existing balance
balances["0xabc123"].amount += 500;
print("Alice's updated balance: ${balances[0xabc123].amount}");

// Using 'in' operator to check for key existence
val addresses = ["0xabc123", "0xdef456", "0xjkl012", "0xmno345"];
for (address in addresses) {
if (address in balances) {
print("Address ${address} exists in the map with balance: ${balances[address].amount}");
} else {
print("Address ${address} does not exist in the map");
}
}

// Combining [] and 'in' operators for safe access
val charlieAddress = "0xghi789";
if (charlieAddress in balances) {
val charlieBalance = balances[charlieAddress];
print("Charlie's balance: ${charlieBalance.amount}, Last updated: ${charlieBalance.lastUpdated}");
}

// Using [] operator with get_or_default for safe access with a default value
val davidAddress = "0xjkl012";
val davidBalance = if (davidAddress in balances) balances[davidAddress] else Balance(0, block.timestamp);
print("David's balance: ${davidBalance.amount}");

// Printing updated balances
for ((address, balance) in balances) {
print("Address: ${address}, Updated Balance: ${balance.amount}");
}
}