Các hàm không có tên
Nói một cách đơn giản, lambda là một hàm không có tên hoặc một hàm ẩn danh. Một đoạn mã thực thi nhỏ, có thể được truyền xung quanh như thể nó là một biến. Trong JavaScript:
function () {}; // very simple
Bây giờ chúng ta hãy xem một số sử dụng cho những lambdas này.
Tóm tắt mã bảng soạn sẵn
Lambdas có thể được sử dụng để trừu tượng hóa mã soạn sẵn. Ví dụ các vòng lặp. Chúng ta thường viết for
và while
lặp lại suốt cả ngày. Nhưng đây là mã không được viết. Chúng ta có thể trích xuất mã bên trong vòng lặp, phần quan trọng nhất của vòng lặp và tóm tắt phần còn lại:
for (var i=0; i<array.length; i++) {
// do what something useful with array[i]
}
bằng cách sử dụng các forEach
đối tượng mảng, trở thành:
array.forEach(function (element, index) {
// do something useful with element
// element is the equivalent of array[i] from above
});
Sự trừu tượng ở trên có thể không hữu ích, nhưng có những hàm bậc cao khác, như forEach
, thực hiện các tác vụ hữu ích hơn nhiều. Ví dụ filter
:
var numbers = [1, 2, 3, 4];
var even = [];
// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
if (numbers[i] % 2 === 0) {
even.push(numbers[i]);
}
}
alert(even);
// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
return number % 2 === 0;
});
alert(even);
Độ trễ thực thi mã
Trong một số môi trường có sẵn khái niệm sự kiện, chúng ta có thể sử dụng lambdas để phản hồi các sự kiện có thể xảy ra tại một thời điểm nào đó.
window.onload = function () {
alert("Loaded");
};
window.setTimeout(function () {
alert("Code executed after 2 seconds.");
}, 2000);
Điều này có thể được thực hiện theo một số cách khác, nhưng những cách đó khá dài dòng. Ví dụ, trong Java có Runnable
giao diện.
Các nhà máy của các chức năng
Cho đến thời điểm này, chúng tôi chỉ sử dụng lambdas cho khả năng đường cú pháp của nó là chủ yếu. Nhưng có những tình huống mà lambdas có thể hữu ích hơn nhiều. Ví dụ, chúng ta có thể có các hàm trả về lambdas. Giả sử chúng ta có một hàm mà chúng ta muốn các giá trị trả về của nó được lưu vào bộ nhớ đệm.
var users = [];
var getUser = function (name) {
if (! users[name]) {
// expensive operations to get a user. Ajax for example
users[name] = user_from_ajax;
}
return users[name];
};
Sau đó, chúng ta có thể nhận thấy rằng chúng ta có một chức năng tương tự:
var photos = [];
var getPhoto = function (name) {
if (! photo[name]) {
// expensive operations to get a user. Ajax for example
photos[name] = photo_from_ajax;
}
return photos[name];
};
Rõ ràng có một mô hình trong đó, vì vậy hãy trừu tượng hóa nó đi. Hãy sử dụng ghi nhớ .
/**
* @param {Array} store Data structure in which we cache lambda's return values
* @param {Function} lambda
* @return {Function} A function that caches the result of calling the lambda param
*/
var memoize = function (store, lambda) {
// return a new lambda
return function (name) {
if (! store[name]) {
// Execute the lambda and cache the result
store[name] = lambda(name);
}
return store[name];
};
};
var getUsers = memoize([], function (name) {
// expensive operations to get a user. Ajax for example
});
var getPhotos = memoize([], function (name) {
// expensive operations to get a photo. Ajax for example
});
Như bạn có thể thấy, bằng cách sử dụng lambdas, chúng tôi đã có thể trừu tượng hóa logic bộ nhớ đệm / ghi nhớ. Nếu ví dụ khác có một số cách giải quyết, tôi tin rằng vấn đề cụ thể này hầu như không được giải quyết bằng cách sử dụng các kỹ thuật khác. Chúng tôi đã quản lý để trích xuất một số mã bảng soạn sẵn quan trọng vào một nơi duy nhất. Chưa kể rằng chúng tôi đã loại bỏ các biến users
và photos
toàn cục.
Nhìn vào hồ sơ của bạn, tôi thấy rằng bạn chủ yếu là người dùng Python. Đối với mẫu trên, Python có khái niệm về trình trang trí. Có rất nhiều ví dụ trên mạng về trang trí ghi nhớ . Sự khác biệt duy nhất là trong Python, bạn rất có thể có một hàm lồng nhau được đặt tên bên trong hàm decorator đó. Lý do là Python chỉ hỗ trợ lambdas một biểu thức. Nhưng khái niệm là như nhau.
Như một ví dụ về việc sử dụng Python lambda. Đoạn mã trên mà chúng tôi đã lọc các số chẵn có thể được biểu diễn bằng Python như thế này:
filter(lambda x: x % 2 == 0, [1, 2, 3, 4])
Dù sao đi nữa, lambdas không mạnh đến thế nếu không đóng cửa. Đóng cửa là điều làm cho khái niệm lambdas trở nên mạnh mẽ. Trong ví dụ ghi nhớ của tôi, tôi đã sử dụng các bao đóng để tạo một bao đóng xung quanh store
tham số. Bằng cách này, tôi có quyền truy cập vào tham số đó ngay cả sau khi memoize
hàm đã trả về kết quả (lambda).