Đây là một câu trả lời bổ sung để giúp giải thích các bản đồ và nếp gấp. Đối với các ví dụ dưới đây, tôi sẽ sử dụng danh sách này. Hãy nhớ rằng, danh sách này là bất biến, vì vậy nó sẽ không bao giờ thay đổi:
var numbers = [1, 2, 3, 4, 5]
Tôi sẽ sử dụng các số trong các ví dụ của mình vì chúng dẫn đến mã dễ đọc. Tuy nhiên, hãy nhớ rằng các nếp gấp có thể được sử dụng cho bất cứ điều gì mà một vòng lặp mệnh lệnh truyền thống có thể được sử dụng cho.
Một bản đồ lấy một danh sách một cái gì đó, và một hàm và trả về một danh sách đã được sửa đổi bằng cách sử dụng hàm. Mỗi mục được truyền cho hàm và trở thành bất cứ thứ gì hàm trả về.
Ví dụ đơn giản nhất về điều này chỉ là thêm một số vào mỗi số trong danh sách. Tôi sẽ sử dụng mã giả để biến nó thành ngôn ngữ bất khả tri:
function add-two(n):
return n + 2
var numbers2 =
map(add-two, numbers)
Nếu bạn đã in numbers2
, bạn sẽ thấy [3, 4, 5, 6, 7]
danh sách đầu tiên có 2 được thêm vào mỗi phần tử. Lưu ý chức năng add-two
đã được đưa ra map
để sử dụng.
Các nếp gấp tương tự nhau, ngoại trừ hàm bạn bắt buộc phải cung cấp cho chúng phải có 2 đối số. Đối số đầu tiên thường là bộ tích lũy (trong một nếp gấp bên trái, là phổ biến nhất). Bộ tích lũy là dữ liệu được truyền trong khi lặp. Đối số thứ hai là mục hiện tại của danh sách; giống như ở trên cho map
chức năng.
function add-together(n1, n2):
return n1 + n2
var sum =
fold(add-together, 0, numbers)
Nếu bạn in sum
bạn sẽ thấy tổng của danh sách các số: 15.
Dưới đây là những gì các đối số để fold
làm:
Đây là chức năng mà chúng tôi đang đưa ra. Việc gấp sẽ vượt qua chức năng của bộ tích lũy hiện tại và mục hiện tại của danh sách. Bất cứ chức năng nào trả về sẽ trở thành bộ tích lũy mới, sẽ được chuyển cho hàm vào lần tiếp theo. Đây là cách bạn "ghi nhớ" các giá trị khi bạn lặp theo kiểu FP. Tôi đã cho nó một hàm có 2 số và thêm chúng.
Đây là tích lũy ban đầu; những gì bộ tích lũy bắt đầu như trước khi bất kỳ mục nào trong danh sách được xử lý. Khi bạn tính tổng các số, tổng số trước khi bạn thêm bất kỳ số nào lại với nhau? 0, mà tôi đã thông qua như là đối số thứ hai.
Cuối cùng, như với bản đồ, chúng tôi cũng chuyển vào danh sách các số để nó xử lý.
Nếu nếp gấp vẫn không có ý nghĩa, hãy xem xét điều này. Khi bạn viết:
# Notice I passed the plus operator directly this time,
# instead of wrapping it in another function.
fold(+, 0, numbers)
Về cơ bản, bạn đang đặt chức năng được chuyển giữa mỗi mục trong danh sách và thêm bộ tích lũy ban đầu vào bên trái hoặc bên phải (tùy thuộc vào việc nó là một nếp gấp bên trái hay bên phải), vì vậy:
[1, 2, 3, 4, 5]
Trở thành:
0 + 1 + 2 + 3 + 4 + 5
^ Note the initial accumulator being added onto the left (for a left fold).
Mà bằng 15.
Sử dụng map
khi bạn muốn biến một danh sách thành một danh sách khác, có cùng độ dài.
Sử dụng fold
khi bạn muốn biến danh sách thành một giá trị, như tổng hợp danh sách các số.
Như @Jorg đã chỉ ra trong các bình luận, "giá trị đơn" không cần phải đơn giản như một con số; nó có thể là bất kỳ đối tượng nào, bao gồm danh sách hoặc bộ dữ liệu! Cách tôi thực sự có các lần nhấp chuột cho tôi là xác định bản đồ theo cách gấp. Lưu ý cách tích lũy là một danh sách:
function map(f, list):
fold(
function(xs, x): # xs is the list that has been processed so far
xs.add( f(x) ) # Add returns the list instead of mutating it
, [] # Before any of the list has been processed, we have an empty list
, list)
Thành thật mà nói, một khi bạn hiểu từng vấn đề, bạn sẽ nhận ra hầu như bất kỳ vòng lặp nào cũng có thể được thay thế bằng một nếp gấp hoặc bản đồ.