Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Cangjie Language: Functions

Tech 2

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: Returns expr (must match return type).
  • return: Equivalent to return (), requires return type Unit.

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(): Unit has type () -> Unit.
  • showNumber(n: Int64): Unit has type (Int64) -> Unit.
  • computeSum(a: Int64, b: Int64): Int64 has 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
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.