官术网_书友最值得收藏!

  • Mastering Dart
  • Sergey Akopkokhyants
  • 801字
  • 2021-08-05 17:19:18

Functions and closures in different scopes

I like Dart because everything is an object. Functions are first-class citizens because they support all the operations that are generally available to other types. This means each function have the following properties:

  • They can be named by a variable
  • They can be passed as an argument to a function
  • They can be returned as the result of a function
  • They can be stored in data structures
  • They can be created in any scope

Let's see where and how can we use functions as usual or as first-class citizens.

Naming functions with a variable

Naming functions by variable means that we can create a reference to a function and assign it to a variable, as shown in the following code:

library function_var;

// Returns sum of [a] and [b]
add(a, b) {
  return a + b;
}

// Operation 
var operation;

void main() {
  // Assign reference to function [add]
  operation = add;
  // Execute operation
  var result = operation(2, 1);
  print("Result is ${result}");}");
}

Here is the result of the preceding code:

Result is 3

We have the add function and the operation variable. We assign the reference of the add function to a variable and call the variable as a function later.

Passing a function as an argument to another function

Passing functions as arguments to other functions can be very useful in cases when we need to implement the strategy design pattern to enable the program code to be selected and executed at runtime, as shown in the following code:

library function_param;

// Returns sum of [a] and [b]
add(a, b) {
  return a + b;
}

// Operation executor
executor(operation, x, y) {
  return operation(x, y);
}

void main() {
  // Execute operation
  var result = executor(add, 2, 1);
  print("Result is ${result}");
}

Here is the result of the preceding code:

Result is 3

The global executor function from the preceding example can call any function that accepts two arguments. You can see the implementation of the strategy design pattern in the form of anonymous functions passed as parameters of methods in collections.

Returning a function as a result of another function

Sometimes, a function can be returned as a result of another function, as shown in the following code:

library function_return;

// Returns sum of [a] and [b]
add(a, b) => a + b;

// Returns difference between [a] and [b]
sub(a, b) => a - b;

// Choose the function depends on [type]
chooser(bool operation) =>operation ? add : sub;

void main() {
  // Choose function depends on operation type
  var operation = chooser(true);
  // Execute it
  var result = operation(2, 1);
  // Result
  print("Result is ${result}");
}

Here is the result of the preceding code:

Result is 3

This option can be very useful in implementing closures.

Storing a function in data structures

We can store a function in data structures in any collection, as shown in the following code:

library function_store;

// Returns sum of [a] and [b]
add(a, b) => a + b;

// Returns difference between [a] and [b]
sub(a, b) => a - b;

// Choose the function depends on [type]
var operations = [add, sub];

void main() {
  // Choose function from list
  var operation = operations[0];
  // Execute it
  var result = operation(2, 1);
  // Result
  print("Result is ${result}");
}

Here is the result of the preceding code:

Result is 3

We have two functions and the array operations in our example that stores references to them.

Closures

A function can be created in the global scope or within the scope of another function. A function that can be referenced with an access to the variables in its lexical scope is called a closure, as shown in the following code:

library function_closure;

// Function returns closure function. 
calculate(base) {
  // Counter store
  var count = 1;
  // Inner function - closure
  return () => print("Value is ${base + count++}");
}

void main() {
  // The outer function returns inner
  var f = calculate(2);
  // Now we call closure
  f();
  f();
}

Here is the result of the preceding code:

Value is 3
Value is 4

We have the calculate function, which contains the count variable and returns a an inner function. The inner function has an access to the count variable because both are defined in the same scope. The count variable exists only within the scope of calculate and would normally disappear when the function exits. This does not happen in this case because the inner function returned by calculate holds a reference to count. The variable has been closed covered, meaning it's within a closure.

Finally, we know what a first-class function is, where we can use them, and how important it is to use closures. Let's move ahead to classes and mixins.

主站蜘蛛池模板: 梅河口市| 微博| 保山市| 平江县| 和顺县| 麻阳| 迁西县| 阿拉善左旗| 渝北区| 永丰县| 保德县| 小金县| 石柱| 上杭县| 广安市| 安福县| 封丘县| 新泰市| 邵武市| 襄城县| 湟中县| 莎车县| 福建省| 仙居县| 正蓝旗| 北安市| 汝州市| 磴口县| 河东区| 视频| 法库县| 嘉峪关市| 昭苏县| 七台河市| 共和县| 曲沃县| 贵定县| 二连浩特市| 永仁县| 多伦县| 永新县|