Functions in Aussom belong to a class. Inside the class you call them
through this; outside, you call them through an instance. This page
covers how to define functions, how arguments work, and the set-block
operator for bulk member assignment.
A function definition has an access modifier, a name, an argument
list, and a body. There is no return-type syntax - you simply
return a value (or omit it, which returns null).
class Math2 {
public add(a, b) {
return a + b;
}
private debug(msg) {
c.log("[debug] " + msg);
}
}
If you leave the access modifier off, the function defaults to
private.
A class may define more than one function with the same name as long as their argument signatures differ - see Overloading below.
class App {
public main(args) {
m = new Math2();
sum = m.add(2, 3);
c.log(sum); // 5
}
}
public functions are callable from outside the class. private
ones are reachable only from other methods on the same class.
class Account {
public deposit(int Amount) {
this.update(Amount);
}
private update(int Delta) {
// only reachable from inside Account
}
}
a = new Account();
a.deposit(50); // OK
// a.update(50); // error: update is private
The simplest case: every argument is required.
public functOne(arg1, arg2, arg3) {
// ...
}
myObj.functOne(1, 2, 3); // OK
myObj.functOne("hi", true, 1.2345); // OK - any types
myObj.functOne("only"); // error: 3 arguments required
Append = value to make an argument optional. Default arguments
must come after any required arguments.
public functOne(arg1, arg2 = true, arg3 = null) {
// ...
}
public functTwo(arg1 = "", arg2 = 10) {
// ...
}
// Required must come before defaults - this is a syntax error
// public bad(arg1 = "", arg2) { ... }
myObj.functOne("test", false, 12345); // all supplied
myObj.functOne("test"); // arg2=true, arg3=null
myObj.functOne(); // error: arg1 is required
myObj.functTwo(); // arg1="", arg2=10
myObj.functTwo("abcde"); // arg2=10
...Use ... as the last argument to accept any number of trailing
values. Inside the function, the special etc list holds them.
public greetAll(string Greeting, ...) {
for (name : etc) {
c.log(Greeting + ", " + name);
}
c.log("(" + #etc + " people)");
}
g = new Greeter();
g.greetAll("Hi", "Avery", "Robin", "Sam");
Output:
Hi, Avery
Hi, Robin
Hi, Sam
(3 people)
The ... must be the last item in the argument list. Putting other
arguments after it is a syntax error.
Aussom is loosely typed by default, but you can annotate arguments with one of the built-in types. The interpreter will then enforce the type at call time.
public functOne(int Num, string Str = "") { }
public functTwo(bool IsTrue = false, double Dbl) { }
public functThree(list Lst, map Mp) { }
public functFour(object Obj) { }
Available type keywords: int, double, bool, string, list,
map, object.
When to annotate:
extern functions where you want the runtime to do
the type check for you.When to leave them off:
The full conventions are in the Style Guide.
Use return to send a value back to the caller. A bare return; or
falling off the end of the function returns null.
public divide(int A, int B) {
if (B == 0) {
return null; // signal: cannot do it
}
return A / B;
}
There is no return type in the function definition. To document the
return value, use an Aussom-Doc @r tag (see the
Style Guide).
A class can define more than one function with the same name, as long as the argument signatures are distinct. The interpreter picks the matching definition at the call site based on the number of arguments and (for typed arguments) their types.
Two definitions with different arity are unambiguous - the call's argument count picks the one that runs.
class Logger {
public log(string Msg) {
c.log("[info] " + Msg);
}
public log(string Level, string Msg) {
c.log("[" + Level + "] " + Msg);
}
}
lg = new Logger();
lg.log("starting"); // calls the 1-arg version
lg.log("warn", "low disk"); // calls the 2-arg version
Two definitions with the same arity overload only if their type annotations differ. Untyped arguments accept anything, so leaving an arg untyped means that overload swallows every call - the typed sibling will never run.
class Formatter {
public render(int N) {
return "int: " + N;
}
public render(string S) {
return "string: \"" + S + "\"";
}
public render(list L) {
return "list of " + #L;
}
}
f = new Formatter();
c.log(f.render(7)); // "int: 7"
c.log(f.render("hi")); // "string: \"hi\""
c.log(f.render([1, 2, 3])); // "list of 3"
If no overload matches the call's signature, the interpreter raises a runtime exception:
Object 'Formatter' has no overload of 'render' matching call signature 'b'.
The signature in the message uses single-letter codes (i for int,
d for double, b for bool, s for string, l for list, m for
map, c for callback, o for object), one per argument.
Default arguments effectively expand into multiple arities. A function with one required and one default argument can be called with one or two arguments. That overlaps with explicit overloads, so mixing them on the same name is a recipe for ambiguity. Pick one strategy per function.
class Greeter {
// OK - distinct arity ranges (1 or 2 args here, exactly 3 below)
public greet(string Name, string Punctuation = "!") {
return "Hello " + Name + Punctuation;
}
public greet(string Greeting, string Name, string Punctuation) {
return Greeting + " " + Name + Punctuation;
}
}
Aussom Server treats every public method on the app class as an HTTP route, identified by name. Overloading public methods on the app class would make routes ambiguous, so the server rejects it at load time. Either pick distinct names, or move the helpers to a separate class.
A set block is a shorthand for assigning many members of an object
at once. The operator is :=. The right side is a map; each key
matches either a public member or a setter method.
class User {
public firstName = "";
public lastName = "";
private age = 30;
public setAge(int Age) {
this.age = Age;
}
}
Use a set block right after construction:
u = new User() := {
firstName: "Robert",
lastName: "Hogan"
};
You can also apply a set block separately, or apply it more than
once. When a key matches a private member, Aussom looks for a
setter named set<Key> (with the first letter capitalized) and
calls it instead.
u = new User();
u := {
firstName: "Robert",
lastName: "Hogan",
age: 42 // matched by setAge(...)
};
The right side can be any expression that evaluates to a map. This makes set blocks handy when you have, say, a row from a database:
mp = { lastName: "Hogan" };
u = new User() := mp;
Limits worth knowing:
set<Key>
method are silently ignored.