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
Function | Description |
---|---|
.add(T): boolean | Adds an element to the end of the list. Always returns true . |
.add(pos: integer, T): boolean | Inserts an element at a given position in the list. Always returns true . |
.add_all(list<T>): boolean | Adds all elements from the given list to the end of the list. |
.add_all(set<T>): boolean | Adds all elements from the given set to the end of the list. |
.add_all(pos: integer, list<T>): boolean | Inserts all elements from the given list at the specified position in the list. |
.add_all(pos: integer, set<T>): boolean | Inserts all elements from the given set at the specified position in the list. |
.clear() | Removes all elements from the list. |
.contains(T): boolean | Checks if the list contains the specified element. |
.contains_all(list<T>): boolean | Checks if the list contains all elements from the given list. |
.contains_all(set<T>): boolean | Checks if the list contains all elements from the given set. |
.empty(): boolean | Returns true if the list is empty, otherwise returns false. |
.index_of(T): integer | Returns the position of the first occurrence of the element in the list. Returns -1 if the element isn't found. |
.remove(T): boolean | Removes the first occurrence of the specified element from the list. Returns true if found. |
.remove_all(list<T>): boolean | Removes all elements from the list that are present in the given list. |
.remove_all(set<T>): boolean | Removes all elements from the list that are present in the given set. |
.remove_at(pos: integer): T | Removes 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(): integer | Returns 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(): text | Returns 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, returningtrue
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
Function | Description |
---|---|
.add(T): boolean | If the element isn't in the set, adds it and returns true . |
.add_all(list<T>): boolean | Adds all elements from the given list to the set. Returns true if at least one element was added. |
.add_all(set<T>): boolean | Adds 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): boolean | Checks if the set contains the specified element. |
.contains_all(list<T>): boolean | Checks if the set contains all elements from the given list. |
.contains_all(set<T>): boolean | Checks if the set contains all elements from the given set. |
.empty(): boolean | Returns true if the set is empty, otherwise returns false. |
.remove(T): boolean | Removes the specified element from the set. Returns true if the element was found and removed. |
.remove_all(list<T>): boolean | Removes 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>): boolean | Removes all elements from the set that are present in the given set. Returns true if at least one element was removed. |
.size(): integer | Returns the number of elements in the set. |
.sorted(): list<T> | Returns a sorted copy of the set as a list. |
.to_text(): text | Returns 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, returningtrue
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
Function | Description |
---|---|
.clear() | Removes all key-value pairs from the map. |
.contains(K): boolean | Checks if the map contains the specified key. |
.empty(): boolean | Returns true if the map is empty, otherwise returns false. |
.get(K): V | Get 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): V2 | Returns 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): V | Removes the key-value pair associated with the specified key from the map. |
.size(): integer | Returns the number of key-value pairs in the map. |
.to_text(): text | Returns 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, returningtrue
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}");
}
}