Dart Generator là một chức năng duy nhất cho phép chúng tôi tạo ra một chuỗi các giá trị. Generators trả về giá trị theo yêu cầu; nó có nghĩa là giá trị được tạo ra khi chúng ta cố gắng lặp qua các trình vòng lặp. Dart cung cấp hỗ trợ tích hợp cho hai loại chức năng của Generators.
- Synchronous Generators
- Asynchronous Generators
Các bài viết liên quan:
Giới thiệu về Dart Generators
Dart Generators là một tính năng mạnh mẽ trong ngôn ngữ lập trình Dart. Chúng cung cấp cách tạo ra và lặp qua các dãy giá trị mà không cần lưu trữ toàn bộ dãy đó trong bộ nhớ. Điều này giúp tiết kiệm tài nguyên và tăng hiệu suất của ứng dụng.
Generators trong Dart được triển khai bằng cách sử dụng hàm đặc biệt được gọi là “sync*”. Khi gặp từ khóa “yield” bên trong hàm “sync*”, giá trị tương ứng sẽ được trả về một cách lười biếng (lazy) và hàm sẽ tạm dừng cho đến khi yêu cầu giá trị tiếp theo.
Cách sử dụng Dart Generators:
- Tạo một Generator: Để tạo một Generator, bạn sử dụng hàm “sync*” và sử dụng từ khóa “yield” để trả về các giá trị. Ví dụ:
Iterable<int> countDown(int start, int end) sync* { for (int i = start; i >= end; i--) { yield i; } }
- Lặp qua các giá trị từ Generator: Để lặp qua các giá trị từ Generator, bạn có thể sử dụng vòng lặp for-in hoặc chuyển đổi Generator thành một danh sách sử dụng phương thức “toList()”. Ví dụ:
void main() { var numbers = countDown(5, 1); for (var number in numbers) { print(number); } // Hoặc chuyển đổi thành danh sách var numberList = countDown(5, 1).toList(); print(numberList); }
- Sử dụng yield* để kết hợp nhiều Generators: Dart cung cấp từ khóa “yield*” để kết hợp nhiều Generators với nhau. Ví dụ:
Iterable<int> evenNumbers() sync* { for (int i = 0; i <= 10; i += 2) { yield i; } } Iterable<int> oddNumbers() sync* { for (int i = 1; i <= 10; i += 2) { yield i; } } Iterable<int> allNumbers() sync* { yield* evenNumbers(); yield* oddNumbers(); }
Dart Generators mang lại nhiều lợi ích, bao gồm:
- Tiết kiệm tài nguyên bộ nhớ vì chỉ cần lưu trữ các giá trị cần thiết.
- Tăng hiệu suất bằng cách trả về các giá trị một cách lười biếng (lazy).
- Linh hoạt và dễ sử dụng trong việc tạo ra các dãy giá trị phức tạp.
- Cho phép kết hợp nhiều Generators với nhau để tạo ra các dãy giá trị phong phú.
Dart Generators là một tính năng quan trọng trong Dart, giúp tối ưu hóa việc lặp qua các dãy giá trị và cải thiện hiệu suất ứng dụng.
Xem thêm Crunch Kali Linux – tạo wordlist trong kali linux
Cách sử dụng Dart Generators
Để sử dụng Dart Generators, bạn có thể tuân theo các bước sau:
- Định nghĩa một Generator: Sử dụng từ khóa “sync*” để định nghĩa một hàm Generator. Bên trong hàm Generator, bạn sử dụng từ khóa “yield” để trả về giá trị. Ví dụ:
Iterable<int> countDown(int start, int end) sync* { for (int i = start; i >= end; i--) { yield i; } }
- Lặp qua các giá trị từ Generator: Bạn có thể sử dụng vòng lặp for-in để lặp qua các giá trị từ Generator. Ví dụ:
void main() { var numbers = countDown(5, 1); for (var number in numbers) { print(number); } }
- Chuyển đổi Generator thành danh sách: Nếu bạn muốn chuyển đổi Generator thành một danh sách, bạn có thể sử dụng phương thức “toList()”. Ví dụ:
void main() { var numberList = countDown(5, 1).toList(); print(numberList); }
- Kết hợp nhiều Generators: Bạn cũng có thể kết hợp nhiều Generators với nhau bằng cách sử dụng từ khóa “yield*” và truyền các Generator khác vào Generator hiện tại. Ví dụ:
Iterable<int> evenNumbers() sync* { for (int i = 0; i <= 10; i += 2) { yield i; } } Iterable<int> oddNumbers() sync* { for (int i = 1; i <= 10; i += 2) { yield i; } } Iterable<int> allNumbers() sync* { yield* evenNumbers(); yield* oddNumbers(); }
Trong ví dụ trên, hàm allNumbers()
kết hợp cả evenNumbers()
và oddNumbers()
để tạo ra một Generator mới chứa tất cả các số từ 0 đến 10.
Dart Generators giúp tạo ra và lặp qua các dãy giá trị một cách linh hoạt và tiết kiệm tài nguyên. Chúng cung cấp cách đơn giản và hiệu quả để làm việc với các tập hợp lớn và tạo ra các dãy giá trị phức tạp trong ngôn ngữ Dart.
Xem thêm Giới thiệu về ngôn ngữ lập trình Dart
Synchronous Generator
Nó trả về một đối tượng có thể lặp lại mang giá trị một cách đồng bộ. Từ khóa năng suất được sử dụng cùng với việc đánh dấu thân chức năng của bộ tạo đồng bộ là đồng bộ * với các giá trị của bộ tạo.
Hãy hiểu ví dụ sau về Generators đồng bộ.
Ví dụ:
main() { print("Dart Synchronous Generator Example."); oddNumber(10).forEach(print); } // syn* functions returns an iterable Iterable<int> oddNumber(int num) sync* { int k = num; while(k >= 0) { if(k%2 == 1) { // 'yield' statement yield k; } k--; } }
Giải trình:
Trong chương trình trên, chúng ta đã khai báo một hàm lẻNumber (10) với vòng lặp foreach không có phần thân của nó. Vòng lặp foreach sẽ lặp lại hàm. Bây giờ, chúng ta đã tạo hàm lẻNumber (10) làm hàm máy phát đồng bộ.
Trong thân hàm, chúng ta đã khởi tạo một biến mới k, biến này gán đối số n. Sau đó, chúng tôi áp dụng vòng lặp while để lặp lại hàm và phần thân của vòng lặp được lặp cho đến khi giá trị của k nhỏ hơn hoặc bằng 0.
Chúng tôi đã thực hiện hoạt động mô-đun trên k để tìm các số lẻ từ Generators. Chúng tôi đã sử dụng câu lệnh lợi nhuận, câu lệnh này sẽ tạm dừng việc thực thi của hàm và trả về giá trị tại một thời điểm. Nó sẽ trả về giá trị của mỗi lần thực thi chức năng của trình tạo. Khi điều kiện của vòng lặp while trở thành sai, thì vòng lặp kết thúc và in ra các số lẻ.
Xem thêm Một số thuật ngữ Bảo mật Internet [RFC 2828]
ASynchronous Generator
Nó trả về một đối tượng luồng mang giá trị không đồng bộ. Từ khóa năng suất được sử dụng cùng với việc đánh dấu thân hàm của bộ tạo không đồng bộ là không đồng bộ * với các giá trị của bộ tạo.
Hãy hiểu ví dụ sau:
Ví dụ –
main() { print("Dart Asynchronous Generator Example."); asyncNaturalsTo(10).forEach(print); } // async* functions returns an stream object Stream<int> asyncNaturalsTo(int num) async* { int k = 0; while(k < num) { // 'yield' statement yield k++; } k--; }
Giải trình:
Đoạn mã trên đã tạo các giá trị không đồng bộ. Hàm asyncNaturalsTo (int num) trả về một luồng đối tượng trong mỗi lần thực thi thân hàm. Ở đây, từ khóa lợi nhuận hoạt động giống như ví dụ trước; nó dừng việc thực thi hàm, trả về giá trị và tiếp tục thực thi cho lần lặp tiếp theo. Nó sẽ xảy ra lặp đi lặp lại cho đến khi thân chức năng bị chấm dứt.
Chúng ta hãy hiểu các khái niệm sau đây liên quan đến chức năng Generators.
yield Keyword
Năng suất trả về một giá trị duy nhất cho chuỗi tại một thời điểm nhưng không dừng hoàn toàn việc thực thi chức năng của trình tạo. Nó trả về một giá trị cho mỗi lần thực thi chức năng của trình tạo.
sync* Keyword –
Từ khóa sync * được sử dụng để khai báo chức năng đồng bộ hóa bộ tạo. Nó trả về giá trị khi chúng ta cố gắng lặp lại giá trị không phải khi nó được tạo. Hãy xem ví dụ sau:
Ví dụ –
void main() { print('creating iterator'); Iterable<int> numbers = getNumbers(4); // Here we are creating iterator print('Iteration starts...'); for (int i in numbers) { print('$i'); // Iterate over the iterator } print('end of main function'); } Iterable<int> getNumbers(int n) sync* { // define generator synchronously print('generator started'); for (int i = 0; i < n; i++) { yield i; } print('generator function ended'); }
Giải trình
Hàm trình tạo ở trên đã tạo ra giá trị khi chúng ta lặp qua trình lặp.
async* Keyword
Từ khóa async được sử dụng để khai báo bộ tạo không đồng bộ. Nó trả về đối tượng luồng. Hãy hiểu ví dụ sau:
Ví dụ
void main() { print('creating iterator'); Stream<int> numbers = getNumbers(4); print('starting to listen...'); numbers.listen((int k) { print('$k'); }); print('end of the main function'); } Stream<int> getNumbers(int number) async* { // declaring asynchronous generator function print('waiting inside generator a 3 seconds :)'); await new Future.delayed(new Duration(seconds: 3)); //sleep 3s print('started generating values...'); for (int i = 0; i < number; i++) { await new Future.delayed(new Duration(seconds: 1)); //sleep 1s yield i; } print('ended generating values...'); }
Xem thêm Cài đặt Dart
Ưu điểm của Dart Generators
Dart Generators mang lại nhiều ưu điểm quan trọng, bao gồm:
- Tiết kiệm tài nguyên bộ nhớ: Generators không lưu trữ toàn bộ dãy giá trị trong bộ nhớ. Thay vào đó, chúng trả về giá trị một cách lười biếng (lazy), chỉ khi nào cần thiết. Điều này giúp giảm tải bộ nhớ và tối ưu hóa hiệu suất ứng dụng khi làm việc với các tập hợp lớn hoặc vô hạn.
- Tăng hiệu suất: Generators cho phép bạn lặp qua và xử lý các dãy giá trị một cách lười biếng. Thay vì tính toán và trả về tất cả các giá trị cùng một lúc, chúng chỉ tính toán và trả về giá trị khi yêu cầu. Điều này giúp cải thiện hiệu suất và tăng tốc độ thực thi của ứng dụng.
- Linh hoạt và tiện ích: Generators cho phép tạo ra các dãy giá trị phong phú và phức tạp một cách dễ dàng. Bạn có thể tạo ra các dãy số, chuỗi, đối tượng, và thậm chí kết hợp nhiều Generators với nhau để tạo ra các dãy giá trị phức tạp hơn. Điều này giúp bạn làm việc với dữ liệu theo các yêu cầu và tình huống cụ thể.
- Quản lý trạng thái: Generators cho phép bạn duy trì trạng thái nội bộ và tiếp tục từ vị trí trước đó khi được gọi lại. Điều này rất hữu ích trong việc xử lý dữ liệu theo phần hoặc theo từng bước, đồng thời tiết kiệm công sức và tối ưu hóa quá trình lặp.
- Tích hợp tốt với các phương pháp khác: Dart Generators hoạt động tốt với các phương pháp khác như vòng lặp, bộ lọc (filter), ánh xạ (map), và giới hạn (take). Điều này giúp bạn xử lý dữ liệu và thực hiện các phép toán trên dãy giá trị một cách dễ dàng và linh hoạt.
Tóm lại, Dart Generators cung cấp một cách tiện lợi và hiệu quả để làm việc với các dãy giá trị và quản lý trạng thái trong ngôn ngữ Dart. Chúng giúp tiết kiệm tài nguyên, tăng hiệu suất và cung cấp tính linh hoạt trong việc xử lý dữ liệu.
Xem thêm Cú pháp cơ bản của Dart
Ứng dụng của Dart Generators
Dart Generators có rất nhiều ứng dụng trong phát triển ứng dụng Dart. Dưới đây là một số ví dụ về cách sử dụng Dart Generators:
- Lặp qua tập hợp lớn dữ liệu: Khi bạn có một tập hợp lớn dữ liệu mà không muốn tải toàn bộ vào bộ nhớ, bạn có thể sử dụng Dart Generators để lặp qua từng phần tử một một cách lười biếng. Điều này giúp tiết kiệm tài nguyên và tăng hiệu suất.
- Tạo các dãy số phức tạp: Dart Generators cho phép bạn tạo ra các dãy số phức tạp dựa trên quy tắc và điều kiện nhất định. Ví dụ, bạn có thể tạo một Generator để tạo dãy số Fibonacci hoặc các dãy số nguyên tố.
- Xử lý dữ liệu theo từng phần: Dart Generators cho phép bạn xử lý dữ liệu theo từng phần một cách lười biếng. Điều này rất hữu ích khi bạn chỉ muốn xử lý một phần nhỏ của dữ liệu mà không cần tải toàn bộ vào bộ nhớ.
- Tạo các tác vụ vô hạn: Generators cung cấp khả năng tạo ra các tác vụ vô hạn mà không cần tạo ra tất cả các giá trị từ đầu. Ví dụ, bạn có thể tạo một Generator để tạo ra các số nguyên vô hạn theo một quy tắc nhất định.
- Kết hợp với các phương pháp khác: Dart Generators có thể được kết hợp với các phương pháp khác như bộ lọc (filter), ánh xạ (map) và giới hạn (take) để thực hiện các phép toán phức tạp trên dãy giá trị.
Với những ứng dụng đa dạng này, Dart Generators cung cấp cho lập trình viên một công cụ mạnh mẽ để xử lý dữ liệu linh hoạt và hiệu quả.
Xem thêm Enumeration trong Dart