Lesson 20 — Closures


0x00 Review and introduction

We have covered the use of Rust functions in two lectures, and in particular learn to use Rust’s higher-order functions, which will become common in future projects. In this lesson, we’ll learn about another form of function — closures, which some people also call anonymous functions, but inaccurately.

Definition of closure 0x01

A Closure, usually referred to as a lexical Closure, is a function that holds external environment variables. The external context is the lexical scope in which the closure is defined. External environment variables, also known as free variables in the functional programming paradigm, are variables that are not defined inside a closure. A function that binds a free variable to itself is a closure. Closures typically consist of a list of arguments (wrapped in two vertical lines) and an expression in the form of the following syntax.

| parameters | expression

Example code is as follows:

let add = |a, b| a + b; // let add: fn(i32, i32) -> i32 = |a, b| a + b; let result = add(1, 2); // let result = add(1.2, 3.4); dbg! (result);Copy the code

Code running results:

result = 3
Copy the code

To explain the above code, the first line declares a function type that is created using closure syntax. We do not specify a type for it; it is inferred from context to be fn(i32, i32) -> i32, equivalent to the second line comment. Look at the code commented out in line 4. If you open it, an error is reported because it is inferred to be of type FN (i32, i32) -> i32 and no other types are accepted. From the above code, it feels like closures are a simplified version of functions.

0x02 from function to closure

Let’s use an example to see what happens when you go from a function to a closure.

So let’s first define a function

fn add(a:i32, b:i32) -> i32 {a + b}
Copy the code

Convert to closures, declared using the let keyword, and the parentheses to pipe symbols. Add a semicolon to end.

let add = |a:i32, b:i32|->i32 {a + b};
Copy the code

Simplify by removing declarations of parameter types. Closures are not as strict as functions in specifying the function type and return value type and removing parentheses.

let add = |a, b| {a + b};
Copy the code

If I keep simplifying,

let add = |a, b| a + b;
Copy the code

0x03 Capture variable

Closures also have the ability to capture and use variables in the scope in which they were defined.

Example code is as follows:

let k = 8; let add_var = |a| a + k; let result = add_var(10); dbg! (result);Copy the code

Code running results:

result = 18
Copy the code

0 x04 summary

This section describes closures for Rust. To summarize the characteristics of closures.

  • Closures are not strictly required to specify parameter and return value types
  • Untyped closures that are called multiple times but pass different types will cause an error
  • Closures can capture and use variables in their scope
  • Closures are usually appropriate for relatively small scenario contexts
  • Closures perform faster than function Pointers (more on this in a later section)

This lesson is just a brief introduction to the use of closures. There is more to closures. I’ll cover closures again in a later Rust advanced class.

0x04 This section source code

020 · StudyRust – Code Cloud – Open Source China (gitee.com)

Next up — iterators.