Cangjie Language: Functions
Defining Functions
In Cangjie, functions are declared using the keyword func. The syntax follows func, then the function name, parameter list, optional return type, and function body. The function name must be a valid identifier. Parameters are enclosed in parentheses (comma-separated for multiple), followed by a colon and the return type (if specified). The body is wrapped in curly braces.
func computeSum(num1: Int64, num2: Int64): Int64 {
return num1 + num2
}
This defines computeSum with two Int64 parameters (num1, num2) and returns their sum as Int64.
Parameter List
A function may have zero or more parameters, categorized as non-named or named based on whether argument labels are required at call sites.
- Non-named parameters: Defined as
param: Type(e.g.,num1: Int64). - Named parameters: Defined as
param!: Type(note the exclamation mark). Example:
func computeSum(num1!: Int64, num2!: Int64): Int64 {
return num1 + num2
}
Named parameters support default values via param!: Type = expr:
func computeSum(num1!: Int64 = 3, num2!: Int64 = 5): Int64 {
return num1 + num2
}
Default values are only allowed for named parameters.
Non-named parameters must precede named parameters. Mixing them in reverse order causes errors:
// Invalid: named parameter before non-named
func invalidFunc(a!: Int64, b: Int64) { /* ... */ }
Parameters are immutable within the function body:
func modifyParam(x: Int64): Int64 {
x = x + 1 // Error: cannot assign to parameter
return x
}
Scope of parameters extends from their definition to the end of the function body. Redefining a parameter name in the body is prohibited:
func scopeExample(a: Int64) {
var aCopy = a // Valid
var a = a + 1 // Error: redefinition of 'a'
}
Return Type
The return type specifies the type of the value produced by the function. Its optional—if omitted, the compiler infers it from the function body.
Explicit return types require all return expressions to match the declared type:
// Error: return type mismatch (tuple vs Int64)
func invalidReturn(a: Int64, b: Int64): Int64 {
return (a, b)
}
Omitting the return type allows inference:
func inferSum(a: Int64, b: Int64) {
return a + b // Inferred return type: Int64
}
Function Body
The body contains executable statements (variable declarations, expressions) and may include nested functions. Use return to exit early:
return expr: Returnsexpr(must match return type).return: Equivalent toreturn (), requires return typeUnit.
Example with local variables:
func calculateProduct(x: Int64, y: Int64) {
var result = 0
result = x * y
return result
}
Local variables shadow outer-scope variables with the same name:
let globalVar = 10
func shadowExample() {
var globalVar = 20 // Shadows outer variable
println(globalVar) // Prints 20
}
The function body’s type is determined by its last element: expression type, or Unit if empty/variable declaration.
Invoking Functions
Call syntax: functionName(arg1, arg2, ...). Arguments (actual parameters) must match the parameter types. Zero arguments use functionName().
- Non-named parameters: Pass expressions directly.
- Named parameters: Pass as
paramName: value.
Non-Named Parameter Call
func computeSum(x: Int64, y: Int64) {
return x + y
}
func main() {
let val1 = 4
let val2 = 6
let total = computeSum(val1, val2)
println("Sum: ${total}") // Output: Sum: 10
}
Named Parameter Call
Named parameters allow reordering arguments:
func adjustValue(base!: Int64, increment!: Int64 = 2) {
return base + increment
}
func main() {
let res1 = adjustValue(base: 5) // Uses default increment=2 → 7
let res2 = adjustValue(increment: 3, base: 5) // Reordered → 8
println("${res1}, ${res2}") // Output: 7, 8
}
Function Types
Functions are first-class citizens in Cangjie—they can be passed as arguments, returned, or assigned to variables. A function type is denoted (ParamTypes) -> ReturnType, where ParamTypes is a comma-separated list of parameter types (enclosed in parentheses).
Examples:
greet(): Unithas type() -> Unit.showNumber(n: Int64): Unithas type(Int64) -> Unit.computeSum(a: Int64, b: Int64): Int64has type(Int64, Int64) -> Int64.createPair(x: Int64, y: Int64): (Int64, Int64)has type(Int64, Int64) -> (Int64, Int64).
Typed Parameters in Function Types
Explicitly name type parameters (all or none):
func main() {
let logger: (event: String, code: Int64) -> Unit = { e, c =>
println("Event: ${e}, Code: ${c}")
}
logger(event: "Error", code: 500) // Output: Event: Error, Code: 500
}
Functions as Parameters
Pass functions to other functions:
func logSum(calculator: (Int64, Int64) -> Int64, a: Int64, b: Int64) {
let result = calculator(a, b)
println("Result: ${result}")
}
func main() {
logSum(computeSum, 3, 4) // Output: Result: 7
}