The syntax for calling a function is
f arg1 arg2 ... argn. The arguments are
separated by spaces and are each expressions, although the only operator with
a higher precedence than a function call is
. to access fields. For example,
to call the print function with the parameters 2 and “three”:
print 2 "three"
Universal Function Call Syntax is fully supported on every function. That is to
say that the call
f arg1 arg2 ... argN is the same as calling the method f with
arg1 as the object:
arg1.f arg2 arg3 ... argN. If
arg1 has a field
the f will refer to the field rather than the global function meaning UFCS cannot
be used if the desired function has the same name as a field of its first parameter.
print 2 //UFCS! 2.print () //UFCS! type Bad = i32 print b = Bad 3 print b //Prints b b.print() //Error: print is not a function, it is an i32!
Function names in Ante are NOT mangled, so multiple functions in the same module with the same name are disallowed. For an alternative to function overloading, traits can be implemented for multiple types with different implementations for each.
Normal function definitions that take a series of parameters and have a return type are in the form:
[modifiers] <name> <params> -> <return type> = <expr>
If a function should have its return type inferred, the return type and arrow can be omitted.
//Examples //Take a unit value as a parameter and return unit sayHi () -> unit = print "hi" //Take one i32 and return an i32 inc x:i32 -> i32 = x + 1 //Take two strings and return a string concat a:Str b:Str -> Str = a ++ b //Take no parameters and infer return type to be i32 one () = 1 //Make the function private, and infer parameter and return types pri add a b = a + b //Modifiers and compiler directives can be all on one line !inline pro ante five () -> i32 = 5 //but the preferred practice is to separate them. //Consider a redesign if the modifiers are excessive. !inline pro ante five () -> i32 = 5
Parameter Type Shorthand
The full syntax for parameters is (var:Type) or var:(Type) but if the type is not a generic type (and thus has no spaces in it), the parenthesis can be omitted.
// v's type needs parenthesis, but i does not push (v: Vec i32) i:i32 -> Str
A lambda is an anonymous function, a function with no name.
To create a lambda, use
\\ instead of the function’s name.
\a b = a ++ b
Lambdas are often used in conjunction with higher order functions when defining a named function to use once would make little sense or when a closure is needed.
l = List.of (0, 3, 4, 9, 10) //double every element of a list map l (\n = 2 * n) //_ can be used to create a lambda with 1 argument l.map (2 * _) //get a list of only "hi" and "hello" ["hi", "yo", "hello", "bye"] |> filter (_ in ["hi", "hello"])
External Function Declarations
Functions external to the linking unit, usually non-Ante functions, can be declared by omitting the body of the function.
printf (cStr:ref c8) ... -> i32 printf "My favorite number is %d\n" 11
Operators can be overloaded for any given set of types by implementing their corresponding trait and creating a function with the name being the operator surrounded in parenthesis.