Lambda Expression

Definition

The syntax of a lambda expression is { p1: T1, ..., pn: Tn => expressions | declarations }.

The content before => is a parameter list. Multiple parameters are separated by commas (,). The parameter name and parameter type are separated by colons (:). There can be no parameter before =>. In addition, => is followed by the lambda expression body, which is a group of expressions or declarations. Similar to a function, the scope of the parameter name of the lambda expression is the lambda expression function body. The scope level can be considered as the same as that of a variable defined in the function body of the lambda expression.

let f1 = { a: Int64, b: Int64 => a + b }

var display = { =>   // Parameterless lambda expression.
    println("Hello")
    println("World")
}

=> cannot be omitted in a lambda expression regardless of whether the expression has parameters, unless it is used as the trailing lambda. The following is an example:

var display = { => println("Hello") }

func f2(lam: () -> Unit) { }
let f2Res = f2{ println("World") } // OK to omit the =>

The type annotation of a parameter can be omitted in a lambda expression. In the following cases, if the parameter type is omitted, the compiler attempts to infer the type. If the compiler cannot infer the type, a compilation error is reported:

  • When a lambda expression is assigned to a variable, its parameter type is inferred based on the variable type.
  • When a lambda expression is used as the argument of a function call expression, its parameter type is inferred based on the parameter type of the function.
// The parameter types are inferred from the type of the variable sum1
var sum1: (Int64, Int64) -> Int64 = { a, b => a + b }

var sum2: (Int64, Int64) -> Int64 = { a: Int64, b => a + b }

func f(a1: (Int64) -> Int64): Int64 {
    a1(1)
}

main(): Int64 {
    // The parameter type of lambda is inferred from the type of function f
    f({ a2 => a2 + 10 })
}

A lambda expression does not support the declaration of the return type. The return type is always inferred from the context. If the return type cannot be inferred, an error is reported.

  • If the return type of a lambda expression is explicitly specified in the context, its return type is the type specified in the context.

    • When a lambda expression is assigned to a variable, its return type is determined based on the variable type.

      let f: () -> Unit = { ... }
      
    • When a lambda expression is used as a parameter, its return type is inferred based on the parameter type of the function call where the lambda expression is used.

      func f(a1: (Int64) -> Int64): Int64 {
          a1(1)
      }
      
      main(): Int64 {
          f({ a2: Int64 => a2 + 10 })
      }
      
    • When a lambda expression is used as a return value, its return type is inferred based on the return type of the function where the lambda expression is used.

      func f(): (Int64) -> Int64 {
          { a: Int64 => a }
      }
      
  • If the type is not specified in the context, the compiler deduces the return type of a lambda expression based on the type of xxx in all return expressions return xxx in the lambda expression body and the type of the lambda expression body.

    • Similar to a common function body, the return type of the content on the right of => is Int64.

      let sum1 = { a: Int64, b: Int64 => a + b }
      
    • If the content on the right of => is empty, the return type is Unit.

      let f = { => }
      

Lambda Expression Call

A lambda expression can be called immediately. The following is an example:

let r1 = { a: Int64, b: Int64 => a + b }(1, 2) // r1 = 3
let r2 = { => 123 }()                          // r2 = 123

A lambda expression can also be assigned to a variable and called using the variable name. The following is an example:

func f() {
    var g = { x: Int64 => println("x = ${x}") }
    g(2)
}