Functions and visibility
Sharing in AEL, the Agent Engineering Language, will follow three clear rules: helpers will stay private to their component, shared functions will be visible by folder, and reusable functions will be imported explicitly. The check will enforce each rule before anything runs.
Status
Planned for AEL Beta 0.0.1. AEL is not available yet.
Package names on this page are preview naming and may change before launch.
Declaring a function
fn with_tax(amount: u64, percent: u64) -> u64 {
return amount + amount * percent / 100;
}
- Every parameter and the result will have explicit types. A function that returns nothing will declare
-> (). - Parameters will not be reassignable unless declared
mut:fn next(mut n: u64) -> u64. - A function will be able to call functions declared further down the same file.
- Every call will name its function directly. Functions will not be values: there will be no closures, and you will not be able to store a function or pass it as an argument.
- Two functions with the same name in one file will be refused; AEL will have no overloading.
The primary of a component will use its role word instead of fn, as in reuse twice(value: i64) -> i64. main will be able to leave out its result when it returns nothing.
Recursive calls will be checked against the target's stack limits: on the smallest boards, a recursion whose depth cannot be bounded will fail to build.
Three kinds of function
| Kind | Declared | Callable from |
|---|---|---|
| Helper function | fn in any component's file | That component and its extension files only |
| Global function | global <name>(…) in <name>.global.ael | Every file in the same folder and every folder below it, with no import |
| Reusable function | reuse <name>(…) in <name>.reuse.ael | A file in the same folder or a folder below it that imports the file in its header |
"Global" will describe where a function is visible, never shared state: AEL will have no global variables.
An example
shop/
round_cents.global.ael # global round_cents(…)
pricing/
discount.reuse.ael # reuse discount(…)
quote.node.ael
shipping/
rates.node.ael
# pricing/discount.reuse.ael
reuse discount(amount: u64, percent: u64) -> u64 {
return amount - share(amount, percent);
}
fn share(amount: u64, percent: u64) -> u64 {
return amount * percent / 100;
}
# pricing/quote.node.ael
import "./discount.reuse.ael";
node quote(amount: u64) -> u64 {
return round_cents(discount(amount, 10));
}
quotewill callround_centswithout an import, becauseround_cents.global.aelis in an ancestor folder.quotewill calldiscountbecause its header importsdiscount.reuse.ael.quotewill not be able to callshare: it is a helper, private todiscount.shipping/rates.node.aelwill be able to callround_cents, but neverdiscount, not even with an import, becausepricing/is a sibling folder.- A file directly in
shop/will not be able to calldiscounteither: a folder will never reach into the folders below it.
Imports
- An import will sit in the file's header, before the first declaration:
import "../welcome.reuse.ael";. - The path will be relative to the importing file and name the whole file name. It will have to lead to the file's own folder or a folder above it, inside the project.
- An import will make one reusable function available, and nothing else: not the file's helpers, and not what that file imports in turn.
- A reusable function that is not imported will be invisible, even in the same folder.
When names collide
- Names in the function itself, and the component's own helpers, will come first.
- Then AEL will look in the caller's folder, then in each folder above it up to the project root. The nearest folder that has an eligible global or imported reusable function of that name will win.
- Two eligible functions of one name in the same folder will be refused as ambiguous.
- If the nearest function has the wrong types, the call will fail. AEL will never fall back to a function further away that happens to fit.
A shared function's body will always use the names visible where it is written. Calling it from another folder will never change which functions its body calls.
Components and packages
These rules will be for shared functions. Components will be connected differently:
- An agent will name its nodes and edges in its configuration, such as
nodes: [summarizer = summarize]. Those references will be typed and may cross folders, but they will never expose a component's helpers. See Agents, nodes and edges. - A package's exports will be named in the header with
refer, such asrefer server/http select get;. See Using packages.