Functions
Functions are values that accept positional arguments and evaluate a body. KataScript uses func for declarations and anonymous function expressions.
Declarations and calls
Section titled “Declarations and calls”func name(parameters): ReturnType { body } defines a named function. Each parameter can optionally have a : Type annotation, and the return annotation is also optional. Call a function with name(arguments); the argument count must match.
func multiply(a: Int, b: Int): Int { ret a * b}print(multiply(6, 7))Annotations are checked at runtime. Named function declarations support forward references within their scope and mutual recursion; execute the definitions before entering a recursive cycle. Recursive evaluation uses the host stack, so keep recursive examples small.
Returns
Section titled “Returns”ret expression immediately leaves the enclosing function. A final expression also supplies the function’s return value. A body ending without a value-producing expression returns nil. A trailing semicolon does not suppress a returned expression value.
func square(n: Int): Int { n * n }func describe(n: Int): Str { if n < 0 { ret "negative" } ret "nonnegative"}print(square(7))print(describe(-1))Postfix ? is another early-return path: it returns an unsuccessful enum value from the current function. See unwrap and propagate.
Closures
Section titled “Closures”func(parameters): ReturnType { body } without a name is an anonymous function expression. Bind it, pass it to another function, or return it. Func is the runtime type for function values; it does not encode a parameter list or return signature.
func make_counter(): Func { let count = 0 ret func(): Int { count = count + 1 ret count }}let next = make_counter()print(next())print(next())A closure captures lexical bindings by shared reference. Reassignment is visible to the closure and its enclosing scope. Shadowing creates a new binding and does not redirect an existing capture. Anonymous functions are ordinary expressions, so they do not receive named-declaration hoisting. See the counter tutorial for independent instances.
Methods
Section titled “Methods”An impl Type { ... } block associates functions with a type. An instance method explicitly takes self as its first parameter; callers omit that argument in value.method(...). A method without self is static and can be called on the type. Self names the implementing type inside the block.
kind Counter { value: Int }impl Counter { func new(): Self { ret Counter { value: 0 } } func add(self, amount: Int) { self.value = self.value + amount }}let counter = Counter.new()counter.add(3)print(counter.value)Mutation copies the final self back to a direct receiver binding. Keep mutating calls in the form counter.add(3); nested receivers do not reliably retain updates. Generic implementations bind parameters using @, as in impl Box[@T]. Add as Interface to declare conformance. See interfaces.
Builtins
Section titled “Builtins”These names are available without an import. They are ordinary identifiers rather than reserved keywords.
| Call | Contract |
|---|---|
print(values...) | Display values separated by spaces, then a newline; return nil |
typeof(value) | Return the argument’s runtime type value; takes exactly one argument |
panic(values...) | Stop evaluation with a runtime error containing the displayed values |
print("answer", 42)print(typeof(42))In the playground, print writes to the output panel. Running a script does not automatically print every expression’s result. Use Res for a failure your caller should handle; panic does not return a recoverable result. See standard library.