Truyền hàm làm đối số
Thuộc phần Logic và luồng điều khiển trong hành trình Dart của Coddy. Bài học 45 trên 65.
Trong lập trình, hàm (function) có thể làm được nhiều hơn là chỉ nhận các giá trị đơn giản như số hoặc chuỗi. Chúng còn có thể nhận các hàm khác làm tham số. Khái niệm mạnh mẽ này được gọi là hàm bậc cao, mở ra những cách hoàn toàn mới để viết code linh hoạt và có thể tái sử dụng.
Khi truyền một hàm làm đối số, về cơ bản bạn đang cho một hàm khác quyền quyết định sẽ thực hiện thao tác nào. Hãy hình dung như bạn đưa cho ai đó một công cụ và để họ chọn cách sử dụng công cụ đó trên các vật liệu khác nhau.
void processNumbers(List<int> numbers, Function operation) {
for (int number in numbers) {
operation(number);
}
}Trong ví dụ này, processNumbers nhận một danh sách và một hàm làm tham số. Tham số hàm operation có thể là bất kỳ hàm nào nhận một số nguyên. Điều này có nghĩa là bạn có thể truyền vào một hàm để in ra các số, nhân đôi chúng hoặc thực hiện bất kỳ thao tác nào khác bạn cần.
Cách làm này giúp code của bạn linh hoạt hơn rất nhiều. Thay vì viết hàm (function) riêng cho từng thao tác có thể xảy ra, bạn viết một hàm có thể xử lý nhiều thao tác khác nhau bằng cách nhận chúng làm tham số.
Thử thách
DễTạo một chương trình minh họa cách truyền hàm làm đối số bằng cách xây dựng một bộ xử lý số linh hoạt. Chương trình sẽ tạo các hàm xử lý khác nhau rồi truyền chúng cho một hàm xử lý chính để áp dụng phép toán lên một danh sách số.
- Đọc chuỗi đầu vào chứa các số được phân tách bằng dấu phẩy (ví dụ:
"1,2,3,4,5") - Đọc chuỗi đầu vào biểu thị loại phép toán (
"double","square"hoặc"increment") - Tách đầu vào thứ nhất thành danh sách chuỗi và chuyển từng chuỗi thành số nguyên
- Tạo ba hàm riêng biệt:
doubleNumbernhận một số nguyên và trả về số đó nhân với 2squareNumbernhận một số nguyên và trả về số đó nhân với chính nóincrementNumbernhận một số nguyên và trả về số đó cộng thêm 1- Tạo một hàm chính có tên
processNumbers, nhận danh sách số nguyên và một hàm làm tham số - Hàm
processNumberscần áp dụng hàm được truyền vào cho từng số trong danh sách và trả về một danh sách mới chứa các kết quả - Dựa trên loại phép toán đầu vào, truyền hàm phù hợp cho
processNumbers - Hiển thị kết quả theo đúng định dạng bên dưới
Ví dụ, nếu đầu vào là "2,4,6,8" và "double", chương trình sẽ in ra:
Number Processor
================
Original numbers: [2, 4, 6, 8]
Operation: double
Processing numbers...
Result: [4, 8, 12, 16]
Operation completed successfullyNếu đầu vào là "3,5,7" và "square", chương trình sẽ in ra:
Number Processor
================
Original numbers: [3, 5, 7]
Operation: square
Processing numbers...
Result: [9, 25, 49]
Operation completed successfullyNếu đầu vào là "10,20,30" và "increment", chương trình sẽ in ra:
Number Processor
================
Original numbers: [10, 20, 30]
Operation: increment
Processing numbers...
Result: [11, 21, 31]
Operation completed successfullyChương trình cần minh họa khái niệm hàm bậc cao bằng cách truyền một trong ba hàm phép toán làm đối số cho hàm processNumbers. Sử dụng câu lệnh điều kiện để xác định hàm cần truyền dựa trên loại phép toán đầu vào. Hàm processNumbers cần duyệt qua danh sách đầu vào, áp dụng hàm được truyền vào cho từng phần tử và thu thập kết quả vào một danh sách mới.
Tự làm thử
import 'dart:io';
void main() {
// Đọc đầu vào
String? numbersInput = stdin.readLineSync();
String? operation = stdin.readLineSync();
// Chuyển chuỗi đầu vào thành danh sách số nguyên
List<int> numbers = numbersInput!.split(',').map((e) => int.parse(e.trim())).toList();
// TODO: Tạo ba hàm thực hiện phép toán (doubleNumber, squareNumber, incrementNumber)
// TODO: Tạo hàm processNumbers nhận một danh sách và một hàm làm tham số
// TODO: Dùng câu lệnh điều kiện để xác định hàm cần truyền vào dựa trên loại phép toán
// TODO: Gọi processNumbers với hàm phù hợp và lưu kết quả
// In kết quả theo định dạng yêu cầu
print('Number Processor');
print('================');
print('Original numbers: $numbers');
print('Operation: $operation');
print('Processing numbers...');
// TODO: In danh sách kết quả tại đây
print('Operation completed successfully');
}Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Logic và luồng điều khiển
1Thao tác nâng cao với danh sách
Thuộc tính danh sách: đầu và cuốiTrạng thái danh sách: isEmpty và isNotEmpĐảo ngược danh sáchThêm vào danh sách: insertXóa khỏi danh sách: removeWhereTìm trong danh sách: indexOfSắp xếp danh sáchXáo trộn danh sáchÔn tập: trình sắp xếp danh sách4Thao tác nâng cao với Map
Duyệt qua MapKiểm tra khóa và giá trịCác thuộc tính của Map: khóa và giá trịThêm có điều kiện: putIfAbsentXóa mục khỏi MapMap lồng nhauÔn tập: Cập nhật kho hàng7Hàm nâng cao
Hàm ẩn danhTruyền hàm làm đối sốTìm hiểu về bao đóngGiới thiệu về đệ quyHàm đệ quy: Đếm ngượcHàm đệ quy: Giai thừaÔn tập: Bộ xử lý danh sách2Thao tác hàm trên danh sách
Biến đổi bằng 'map'Lọc bằng 'where'Dùng '.toList()'Kiểm tra điều kiện bằng 'any'Điều kiện với 'every'Tìm phần tử bằng 'firstWhere'Ôn tập: lọc dữ liệu5Dự án: Tính tiền giỏ hàng
Thiết lập dự ánThêm mặt hàng vào giỏ8Dự án: Trình phân tích văn bản đơn giản
Tổng quan và thiết lập dự ánĐếm ký tự3Tập hợp
Tập hợp là gì?Tạo tập hợpThêm và xóa phần tử khỏi tập hợpKiểm tra phần tử trong tập hợpChuyển danh sách thành tập hợpPhép hợp của các tập hợpPhép giao của các tập hợpPhép hiệu của các tập hợpÔn tập: danh sách khách mời không trùng lặpTự luyện tập: Trình biên dịch Dart online