Collections

Adama has three primary collection types: list<T>, map<K,V>, and arrays (T[]). This is where you'll spend a lot of your time when working with data.

List Methods

Lists are dynamic, ordered collections. You typically get them from table queries via iterate.

size()

Returns how many elements are in the list.

record Record {
  public int id;
}

table<Record> _records;

public formula record_count = (iterate _records).size();
list<int> numbers;
int count = numbers.size();
Parameter Type Description
(none) - -

Returns: int - The number of elements


toArray()

Converts the list to a fixed-size array.

procedure foo() {
  list<int> numbers;
  int[] arr = numbers.toArray();
}
Parameter Type Description
(none) - -

Returns: T[] - An array containing all list elements


reverse()

Gives you a new list with the elements in reverse order.

procedure foo() {
  list<int> numbers;
  list<int> reversed = numbers.reverse();  // [3, 2, 1]
}
Parameter Type Description
(none) - -

Returns: list<T> - A new list with reversed order


skip(n)

Returns a new list with the first n elements removed. Good for pagination.

procedure foo() {
  list<int> numbers;
  list<int> skipped = numbers.skip(2);  // [3, 4, 5]
}
Parameter Type Description
n int Number of elements to skip

Returns: list<T> - A new list without the first n elements


drop(n)

Returns a new list with the last n elements removed.

procedure foo() {
  list<int> numbers;
  list<int> dropped = numbers.drop(2);  // [1, 2, 3]
}
Parameter Type Description
n int Number of elements to remove from end

Returns: list<T> - A new list without the last n elements


flatten()

Takes a nested list structure and flattens it into a single list.

procedure foo() {
  list<list<int>> nested;
  list<int> flat = nested.flatten();  // [1, 2, 3, 4]
}
Parameter Type Description
(none) - -

Returns: list<U> - A flattened list where U is the inner list type


manifest()

Extracts values from a list<maybe<T>>, keeping only the ones that actually have values. The name is a bit unusual (I know), but it "manifests" the present values out of the maybe wrappers.

procedure foo() {
  list<maybe<int>> maybes;
  list<int> values = maybes.manifest();  // [1, 3]
}
Parameter Type Description
(none) - -

Returns: list<U> - A list of the non-empty values


Index Access

Lists support index access with brackets. It returns maybe<T> since the index might be out of bounds -- no exceptions, just an empty maybe.

procedure foo() {
  list<int> numbers;
  maybe<int> first = numbers[0];
  maybe<int> tenth = numbers[9];  // Empty if list has fewer than 10 elements

  if (first as value) {
    // Use value safely
  }
}

Map Methods

Maps are key-value dictionaries. Keys must be types that work as map domains: int, long, string, principal.

size()

Returns the number of entries.

map<string, int> scores;
int count = scores.size();
Parameter Type Description
(none) - -

Returns: int - The number of key-value pairs


has(key)

Checks if a key exists.

map<string, int> scores;
bool hasAlice = scores.has("Alice");
Parameter Type Description
key K The key to check for

Returns: bool - True if the key exists


insert(map)

Merges another map into this one.

procedure foo() {
  map<string, int> scores1;
  map<string, int> scores2;
  map<string, int> combined = scores1.insert(scores2);
}
Parameter Type Description
map map<K,V> The map to merge

Returns: map<K,V> - The merged map


remove(key)

Removes an entry and returns the value that was there (if any).

procedure foo() {
  map<string, int> scores;
  maybe<int> removed = scores.remove("Alice");
}
Parameter Type Description
key K The key to remove

Returns: maybe<V> - The removed value, or empty if key didn't exist


clear()

Removes everything.

procedure foo() {
  map<string, int> scores;
  scores.clear();
}
Parameter Type Description
(none) - -

Returns: void


min()

Returns the entry with the smallest key.

procedure foo() {
  map<int, string> lookup;
  maybe<pair<int, string>> minimum = lookup.min();
}
Parameter Type Description
(none) - -

Returns: maybe<pair<K,V>> - The entry with the smallest key, or empty if map is empty


max()

Returns the entry with the largest key.

procedure foo() {
  map<int, string> lookup;
  maybe<pair<int, string>> maximum = lookup.max();
}
Parameter Type Description
(none) - -

Returns: maybe<pair<K,V>> - The entry with the largest key, or empty if map is empty


Key Access

Maps support bracket notation for key-based access. Returns maybe<V> because the key might not be there.

procedure foo() {
  map<string, int> scores;
  maybe<int> aliceScore = scores["Alice"];

  if (aliceScore as score) {
    // Use score safely
  }
}

Key Mutation

You can also mutate maps directly through bracket notation:

map<int, int> notifications;
int thread_id = 1;

procedure foo() {
  // Set a value
  notifications[thread_id] = 5;

  // Increment a value
  notifications[thread_id]++;

  // Remove a key
  notifications.remove(thread_id);

  // Clear all entries
  notifications.clear();
}

Iterating Maps

Use foreach to walk over map entries:

map<string, int> scores;

procedure foo() {
  foreach (kvp in scores) {
    string name = kvp.key;
    int score = kvp.value;
    // Process each entry
  }
}

Array Methods

Arrays are fixed-size. You create them from literals or by converting lists.

size()

Returns the number of elements.

procedure foo() {
  int[] numbers = [1, 2, 3, 4, 5];
  int length = numbers.size();  // 5
}
Parameter Type Description
(none) - -

Returns: int - The number of elements


Index Access

Arrays support direct index access.

procedure foo() {
  int[] numbers = [1, 2, 3];
  maybe<int> first = numbers[0];  // 1
  maybe<int> second = numbers[1]; // 2
}

Working with Tables and Iterate

The most common way to get lists in Adama is through iterate on tables. This creates reactive lists that update automatically when the underlying data changes.

Basic Iteration

record Player {
  public int id;
  public string name;
  public int score;
}

table<Player> _players;

// Basic list from table
public formula all_players = iterate _players;

// With filtering
public formula high_scorers = iterate _players where score > 100;

// With ordering
public formula leaderboard = iterate _players order by score desc;

// With limit
public formula top_three = iterate _players order by score desc limit 3;

Combining Operations

record Player {
  public int id;
  public string name;
  public int score;
  public bool active;
}

table<Player> _players;

// Skip and limit for pagination
public formula page_two = iterate _players
  order by name asc
  offset 10
  limit 10;

// Filter, order, and limit
public formula best_active = iterate _players
  where active == true
  order by score desc
  limit 5;

Bulk Operations

Lists from iterate support bulk assignment and method execution. This is one of my favorite features -- you can mutate entire result sets in one shot:

record Player {
  public int id;
  public int score;
  public bool active;
  method double_score() {
    score = score * 2;
  }
}

table<Player> _players;

// Bulk field assignment
procedure reset_scores() {
  (iterate _players).score = 0;
}

// Bulk method execution
procedure double_all() {
  (iterate _players).double_score();
}

// Bulk deletion
procedure remove_inactive() {
  (iterate _players where active == false).delete();
}

Reduce Operations

The reduce keyword groups list items by a field and applies a function to each group. It's basically GROUP BY from SQL.

record Sale {
  public int id;
  public string category;
  public double amount;
}

table<Sale> _sales;

// Group sales by category
public formula sales_by_category =
  iterate _sales
  reduce on category via (@lambda items: items);

// Count sales per category
public formula category_counts =
  iterate _sales
  reduce on category via (@lambda items: items.size());

Method Summary Tables

List Methods

Method Description Returns
size() Number of elements int
toArray() Convert to array T[]
reverse() Reverse order list<T>
skip(n) Skip first n elements list<T>
drop(n) Remove last n elements list<T>
flatten() Flatten nested lists list<U>
manifest() Extract maybe values list<U>
[index] Access by index maybe<T>

Map Methods

Method Description Returns
size() Number of entries int
has(key) Check if key exists bool
insert(map) Merge maps map<K,V>
remove(key) Remove entry maybe<V>
clear() Remove all entries void
min() Entry with minimum key maybe<pair<K,V>>
max() Entry with maximum key maybe<pair<K,V>>
[key] Access by key maybe<V>

Array Methods

Method Description Returns
size() Number of elements int
[index] Access by index maybe<T>

Common Patterns

Pagination

record Item {
  public int id;
  public datetime created;
}

table<Item> _items;

view int page;
int page_size = 10;

bubble paginated_items = iterate _items
  order by created desc
  offset (@viewer.page * page_size)
  limit page_size;

Finding Elements

record User {
  public int id;
  public string role;
}

table<User> _users;

// Find first match
public formula first_admin =
  (iterate _users where role == "admin" limit 1)[0];

// Check if any match exists
public formula has_admin =
  (iterate _users where role == "admin" limit 1).size() > 0;

Transforming Lists

record Player {
  public int id;
  public string name;
}

table<Player> _players;

// Use formulas to transform list data
public formula player_names =
  iterate _players order by name asc;
// Client can extract just the names from the list
Previous Datetime
Next Statistics