Functions¶
Functions define the interface of your contract. StxScript supports three visibility levels through decorators, along with generic functions and lambda expressions.
Function Declarations¶
A basic function has a name, parameters with types, a return type, and a body:
Generated Clarity:
By default, functions are private (internal to the contract).
Decorators¶
Decorators control function visibility:
| Decorator | Clarity | Description |
|---|---|---|
| (none) | define-private |
Internal only, not callable from outside |
@public |
define-public |
Callable externally, must return Response |
@readonly |
define-read-only |
Callable externally, cannot modify state |
Public Functions¶
Public functions are the external interface of your contract. They must return a Response type:
@public
function transfer(to: principal, amount: uint): Response<bool, uint> {
if (amount == 0u) {
return err(1u);
}
return ok(true);
}
Generated Clarity:
Read-Only Functions¶
Read-only functions can be called externally but cannot modify contract state (no var-set, no map mutations):
@readonly
function get_balance(account: principal): uint {
match balances.get(account) {
some(balance) => balance,
none => 0u
}
}
Generated Clarity:
Private Functions¶
Functions without a decorator are private. They can only be called by other functions in the same contract:
Generated Clarity:
Parameters¶
Parameters require explicit type annotations:
function process(
sender: principal,
amount: uint,
memo: Optional<string>
): Response<bool, uint> {
return ok(true);
}
The semantic analyzer checks argument counts at call sites:
Return Types¶
All functions must declare a return type:
function get_count(): uint {
return counter;
}
@public
function reset(): Response<bool, uint> {
counter = 0u;
return ok(true);
}
The semantic analyzer validates return types match the declared type.
Name Conversion¶
StxScript converts camelCase function names to kebab-case in Clarity output:
| StxScript | Clarity |
|---|---|
getBalance |
get-balance |
transferFrom |
transfer-from |
totalSupply |
total-supply |
snake_case names are also converted:
| StxScript | Clarity |
|---|---|
get_balance |
get-balance |
transfer_from |
transfer-from |
Lambda Expressions¶
Lambda expressions (arrow functions) define inline functions:
Lambdas are commonly used with higher-order list operations:
let doubled = map(numbers, (x) => x * 2u);
let evens = filter(numbers, (x) => x % 2u == 0u);
let sum = fold(numbers, 0u, (acc, x) => acc + x);
Generated Clarity (fold example):
Generic Functions¶
Functions can be parameterized over types using angle brackets:
function identity<T>(value: T): T {
return value;
}
function swap<T, U>(a: T, b: U): { first: U, second: T } {
return { first: b, second: a };
}
Multiple Type Parameters¶
Calling Generic Functions¶
Type parameters can be explicitly specified:
Function Patterns¶
Guard Pattern¶
Check preconditions early and return errors:
@public
function withdraw(amount: uint): Response<bool, uint> {
if (amount == 0u) {
return err(ERR_INVALID_AMOUNT);
}
if (amount > get_balance(tx-sender)) {
return err(ERR_INSUFFICIENT_BALANCE);
}
// ... proceed with withdrawal
return ok(true);
}
Delegation Pattern¶
Private helpers called by public functions:
function is_authorized(caller: principal): bool {
return caller == contract_owner;
}
@public
function admin_action(): Response<bool, uint> {
if (!is_authorized(tx-sender)) {
return err(ERR_UNAUTHORIZED);
}
return ok(true);
}
Next Steps¶
- Expressions - Operators used in function bodies
- Control Flow - Branching and looping
- Error Handling - Response types in detail