- Declared with
fun, PascalCase names:fun Compute(a: Int): Int { ... } - Pure functions:
pure fun Hash(o: Object): Int { ... }- Side-effect free; VM may cache results.
- If parameters include user-defined reference types, those types must implement
IHashable.
-
class Name implements IFace1, IFace2 { ... }-
No class inheritance.
-
Access modifiers are mandatory on fields and methods.
-
Fields use
val(immutable) orvar(mutable):private val Prefix: Stringpublic var Count: Int
-
Methods must declare access and can be
override/pure:public override fun Run(): Int { ... }
-
Static fields supported; writing
static varis unsafe. -
Destructor: optional, overrides the implicit virtual destructor from
Object.- Syntax:
public destructor(): Void { ... }(no parameters, no return). - Called automatically by GC finalization; manual calls are unsafe.
- Syntax:
-
-
interface IGreeter { fun Greet(name: String): String; }- Methods are public and virtual by default.
- No fields, no bodies.
- Create type aliases for better readability:
typealias UserId = Int - Can be used anywhere a type is expected:
fun ProcessUser(id: UserId): Void
- Namespace resolution with
::(e.g.,sys::Print), declared withnamespacekeyword.
- Preprocessor commands:
#import,#define,#ifdef,#ifndef,#else,#undef. - Multiple
#definecommands can be used to define the same symbol, as well as#undefto undefine a symbol. #importdoes not include the file at the location of the#importcommand. It adds a dependency for the current file, and after all dependencies are collected, they are included in the final compilation. Order is defined by the topological sort of the dependency graph and lexicographic order of the files to avoid cyclical dependencies and double inclusion.
Note:
#definecannot be used to really define something, it is a way to control what code will be used.
- Classes or interfaces can declare a special
callmember that makes instances callable like functions. - Classes define
call, it may have other members. - Interfaces contain undefined
callmember (maybe not one, with all interface rules applying). - A function literal
fun(...) : T { ... }can be coerced to a interface type that exposes a compatiblecall(...) : T(and only this).
Example:
interface CustomFunctional {
call(a: Int?, b: Int?): Int
}
class DefinedFunctional {
public var Multiplier: Int
public fun DefinedFunctional(multiplier: Int): DefinedFunctional {
this.Multiplier = multiplier
return this
}
// Defines the callable behavior; pure body allowed
public call(secondMultiplier: Int): Int = fun(secondMultiplier: Int): Int {
return Multiplier * secondMultiplier
}
}
val AddNullable: CustomFunctional = pure fun(a: Int?, b: Int?): Int {
val aVal: int = a ?: 0 // Conversion from Int? to int
val bVal: int = b ?: 0
return aVal + bVal
}
fun Main(args: StringArray): Int {
// Constructor call then functional call via `call`
return AddNullable(2, DefinedFunctional(-1)(2)) // Implicit conversion from literals
}