Method Calls and Field Access
Cambrian uses dot notation for both field access on records and method calls on built-in types. Bracket notation provides indexed access to maps and collections.
Field Access
Record fields are accessed with the dot operator:
let seller = listing.seller;
let is_live = listing.active;
let max = m_config.limits.max_deposit;
Member state variables are accessed by name within member transforms, where clauses, macros, and route actions:
where m_balance >= amount : throw 100
Map Access
HashMap values are accessed with bracket notation:
let bal = m_balances[account];
Bracket access never fails: a missing key yields the value type’s default
(0 for numbers, false for bool, and so on), just like a Solidity
mapping. A stored 0 and an absent key look the same through []; use
m.exists(k) (or its alias m.contains(k)) when membership matters:
let known = m_balances.exists(account);
Method Calls
Built-in types provide methods that are called with dot notation:
Vec Methods
let size = m_items.len();
let first = m_items[0];
let empty = m_items.len() == 0;
push appends an element; it is used as the result of a member transform
(in add(x) => m_items.push(x)).
HashMap Methods
let has_key = m_map.exists(key);
let also_has = m_map.contains(key);
let empty = m_map.is_empty();
Writes happen in member transforms: m.insert(k, v), m.update(k, v), and
m.remove(k) each return the updated map.
Option Values
Option<T> has no accessor methods: unwrap, unwrap_or, is_some,
is_none, and expect are rejected at compile time, as are .get / .set
on maps and vectors (use m[k], v[i], and the member-transform writes).
Take an Option apart with match:
let val = match opt {
some(v) => v,
none => 0
};
String Methods
let size = name.len();
len() on a String counts UTF-8 bytes, not characters.
Method Chaining
Map writes return the updated map, so they can be chained:
m_balances: HashMap<address, U256> {
in transfer(to, amount) => m_balances
.insert(msg::sender, m_balances[msg::sender] - amount)
.insert(to, m_balances[to] + amount)
}
This pattern is common in member transforms where multiple map updates happen atomically.
Type Casts
The as keyword casts a value to a different type:
let wide = narrow_val as u64;
let big = amount as U256;
Widening between unsigned integer types happens automatically: in
small + x with small: u8 and x: u64, small is widened to u64.
An explicit as is needed to narrow, or to pin a specific width. See
Type Widening and
Arithmetic and Logic.
Common Cast Patterns
// Narrowing: checked -- reverts if the value does not fit
let byte_val = large_num as u8;
// Widening: always safe
let big_val = small_num as u128;
Narrowing with as does not truncate: if the value is out of range for
the target type, the transaction reverts.
Combining Access Patterns
Field access, method calls, and bracket access can be combined freely:
let bidder_balance = m_auctions[auction_id].highest_bid.amount;
let last_amount = m_bids[m_bids.len() - 1].amount;
Pure Function Calls
Top-level pure functions are called by name (without dot notation):
let fee = compute_fee(amount, rate);
let clamped = clamp(value, min, max);
Macro Invocation
Entity-scoped macros are called with the @ prefix:
where @is_owner() : throw 100
Macros look like function calls but can access entity state. See Macros for details.