DEV Community

SameX
SameX

Posted on

HarmonyOS Next closures and nested functions collaborate with practical operations: from scope isolation to state encapsulation

This article aims to deeply explore the technical details of Huawei HarmonyOS Next system and summarize them based on actual development practices.It is mainly used as a carrier of technology sharing and communication, and it is inevitable to miss mistakes. All colleagues are welcome to put forward valuable opinions and questions in order to make common progress.This article is original content, and any form of reprinting must indicate the source and original author.

1. Analysis of the "symbiotic relationship" between closures and nested functions

In the Cangjie language of HarmonyOS Next, there is a natural synergy between nested functions and closures: nested functions naturally have closure characteristics, which can capture variables in the outer scope, forming the compound ability of "function nesting + state encapsulation".This combination performs well in scenarios where logical hierarchy and state isolation are required.

1.1 The nature of closures of nested functions

Nested functions will automatically capture variables in outer scope to form closures.Even if the outer function is executed, the nested function can still access the captured variables to achieve persistence of the state.

Example: Nested functions capture outer variables

func outerFunc() {
let outerVar = 10 // external local variable
  func innerFunc() {
println(outerVar) // Nested functions capture outerVar and form closure
  }
return innerFunc // Returns nested functions, the closure keeps a reference to outerVar
}

let closure = outerFunc()
closure() // Output: 10 (outerFunc has been executed, the closure is still alive)
Enter fullscreen mode Exit fullscreen mode

1.2 The impact of scope hierarchy on closures

The scope level of nested functions determines the range of variables that can be captured:

  • Global Function: Unable to capture local variables of other functions;
  • External function: Can capture local and global variables of outer function;
  • Multi-layer nested functions: Can capture all outer scope variables (such as grandfather functions, parent functions, etc.).

Multi-layer nesting example

func grandParent() {
  let a = 1
  func parent() {
    let b = 2
    func child() {
println(a + b) // Capture grandParent's a and parent's b
    }
    child()
  }
  parent()
}
Enter fullscreen mode Exit fullscreen mode

2. The practice of "closure enhancement" scenarios of nested functions

2.1 State encapsulation: closure implementation of counter

Encapsulate private state by nested functions to avoid global variable pollution, while maintaining state with the persistence of closures.

func createCounter(): () -> Int64 {
var count = 0 // Local variables of outer function, captured by nested functions
  func increment() -> Int64 {
    count += 1
    return count
  }
return increment // Return nested function, closure saves count state
}

//Usage scenario: multiple calls return different results
let counter = createCounter()
println(counter()) // 1
println(counter()) // 2
Enter fullscreen mode Exit fullscreen mode

2.2 Logical layering: disassembly of complex algorithms

The complex algorithm is broken down into multi-layer nested functions, the inner layer functions focus on specific logic, the outer layer functions control the process, and the intermediate results are shared through closures.

Example: Nested Implementation of Quick Sorting Algorithm

func quickSort<T: Comparable>(array: Array<T>) -> Array<T> {
  if array.isEmpty { return array }
  let pivot = array[array.count/2]
// Nested functions: partition logic
  func partition(arr: Array<T>) -> (Array<T>, T, Array<T>) {
    var less = [T]()
    var greater = [T]()
    for item in arr {
      if item < pivot { less.append(item) }
      else if item > pivot { greater.append(item) }
    }
    return (less, pivot, greater)
  }
  let (less, pivot, greater) = partition(array)
  return quickSort(less) + [pivot] + quickSort(greater)
}

// Call: The closure of nested function partition captures the pivot variable
let numbers = [3, 1, 4, 2]
println(quickSort(numbers)) // Output: [1, 2, 3, 4]
Enter fullscreen mode Exit fullscreen mode

3. "Limited Intersection" between closures and nested functions

3.1 The effect of escape restrictions on nested functions of mutable variables

If a nested function captures a var variable, the function cannot be used as a first-class citizen (such as assigned to a variable or passed as a parameter), and is only allowed to be called directly or used as a return value in constrained scenarios.

Error Example: Capture var's nested function passed as a parameter

func outer() {
  var x = 10
func inner() { x += 1 } // Capture var variable x
  func callInner(fn: () -> Unit) {
fn() // Error: inner function captures var variable and cannot be passed as a parameter
  }
  callInner(inner)
}
Enter fullscreen mode Exit fullscreen mode

Correct example: Called only in the current scope

func outer() {
  var x = 10
  func inner() { x += 1 }
inner() // Legal call
println(x) // Output: 11
}
Enter fullscreen mode Exit fullscreen mode

3.2 Effect of nesting depth on performance

Deep nesting may cause the closure chain to be too long and increase memory overhead.It is recommended to control the nesting level within 3 layers, and complex logic is split through classes or modules.

Counterexample: Four-layer nesting (poor performance and readability)

func level1() {
  func level2() {
    func level3() {
      func level4() {
        println("Deep nested")
      }
      level4()
    }
    level3()
  }
  level2()
}
Enter fullscreen mode Exit fullscreen mode

Optimization: Extracted as independent functions

func level4() { println("Deep nested") }
func level3() { level4() }
func level2() { level3() }
func level1() { level2() }
Enter fullscreen mode Exit fullscreen mode

4. Typical applications in Hongmeng Development: Best practices for closures and nested functions

4.1 Event logic encapsulation of UI components

In ArkUI, the event processing logic is separated from component definitions through nested functions, keeping the code neat.

@Entry
struct ButtonWithCounter {
  private count = 0

  build() {
    Column {
      Text("Click count: \(count)")
      Button("Click me")
.onClick(handleClick) // Call nested functions
    }
  }

// Nested functions: handle click events and update status
  private func handleClick() {
    count += 1
    println("Clicked: \(count)")
  }
}
Enter fullscreen mode Exit fullscreen mode

4.2 Resource Management: Closure Encapsulation of File Operations

Take advantage of the closure feature of nested functions to ensure that resources (such as file handles) are properly released after use and avoid leakage.

func processFile(path: String) {
  func openFile(): FileHandle {
    let handle = FileSystem.open(path, mode: .Read)
// Nested function: Close the handle after reading the file content
    func readAndClose() {
      let content = handle.readAll()
handle.close() // closure captures handle, ensures close after calling
      println(content)
    }
    readAndClose()
  }
  openFile()
}
Enter fullscreen mode Exit fullscreen mode

5. Guide to performance optimization and pit avoidance

5.1 "Minimum Principle" of Closure Capture

Capture only necessary variables, avoid capturing large objects or redundant states, and reduce memory usage.

Optimization example: Avoid capturing the entire array

func processArray(array: Array<Int64>) {
let sum = array.sum() // Calculate the sum in advance, the closure only captures the result
  func printSum() {
println("Sum: \(sum)") // Capture sum, not the entire array
  }
  printSum()
}
Enter fullscreen mode Exit fullscreen mode

5.2 Compilation period check: Use IDE prompts to avoid errors

With the help of the compilation period prompts of the Hongmeng development tool, closure capture errors (such as variables are not defined or not initialized) are discovered in a timely manner.

Common Error Tips

  • Cannot capture 'x' which is not defined: The variable is not declared within the closure scope;
  • Variable 'x' is not initialized: The variable is not initialized when the closure is defined.

Conclusion: The philosophy of "co-design" of nested functions and closures

The combination of closures and nested functions is the core method for implementing "modular, state encapsulation" in HarmonyOS Next.By rationally utilizing nested structures and closure features, developers can:

  1. Isolate complex logic: Encapsulate algorithm details in nested functions to expose concise interfaces;
  2. Security management status: Use the privacy of closures to avoid global state pollution;
  3. Optimize performance: Control the life cycle and memory overhead of the closure through the scope level.

In actual development, the principle of "logical cohesion and clear hierarchy" should be followed, so that nested functions and closures become powerful tools to improve code quality and development efficiency.

Top comments (0)