นี่คือคำตอบเพิ่มเติมเพื่อช่วยอธิบายแผนที่และแผ่นพับ สำหรับตัวอย่างด้านล่างฉันจะใช้รายการนี้ โปรดจำไว้ว่ารายการนี้ไม่เปลี่ยนรูปดังนั้นจะไม่มีการเปลี่ยนแปลง:
var numbers = [1, 2, 3, 4, 5]
ฉันจะใช้ตัวเลขในตัวอย่างของฉันเพราะมันทำให้อ่านรหัสได้ง่าย จำไว้ว่าสามารถใช้การพับได้กับทุกสิ่งที่จำเป็นต้องใช้การวนซ้ำแบบดั้งเดิม
แผนที่จะนำรายชื่อของบางสิ่งบางอย่างและฟังก์ชั่นและการกลับรายการที่ได้รับการปรับเปลี่ยนโดยใช้ฟังก์ชั่นที่ แต่ละรายการจะถูกส่งผ่านไปยังฟังก์ชั่นและจะกลายเป็นสิ่งที่ฟังก์ชั่นกลับมา
ตัวอย่างที่ง่ายที่สุดคือการเพิ่มจำนวนลงในแต่ละรายการในรายการ ฉันจะใช้ pseudocode เพื่อทำให้เป็นผู้ไม่เชื่อเรื่องภาษา:
function add-two(n):
return n + 2
var numbers2 =
map(add-two, numbers)
หากคุณพิมพ์numbers2
คุณจะเห็น[3, 4, 5, 6, 7]
ว่ารายการแรกที่มี 2 เพิ่มไปยังแต่ละองค์ประกอบ สังเกตฟังก์ชั่นที่add-two
ได้รับmap
การใช้งาน
Fold s มีลักษณะคล้ายกันยกเว้นฟังก์ชันที่คุณต้องการให้มีอาร์กิวเมนต์ 2 ตัว อาร์กิวเมนต์แรกมักจะเป็นตัวสะสม (เป็นรอยพับด้านซ้ายซึ่งเป็นเรื่องธรรมดาที่สุด) แอคคูมูเลเตอร์คือข้อมูลที่ถูกส่งผ่านขณะวนลูป อาร์กิวเมนต์ที่สองคือรายการปัจจุบันของรายการ เช่นเดียวกับข้างต้นสำหรับmap
ฟังก์ชั่น
function add-together(n1, n2):
return n1 + n2
var sum =
fold(add-together, 0, numbers)
หากคุณพิมพ์sum
คุณจะเห็นผลรวมของรายการตัวเลข: 15
นี่คือสิ่งที่อาร์กิวเมนต์ที่ต้องfold
ทำ:
นี่คือฟังก์ชั่นที่เราให้พับ การพับจะส่งผ่านฟังก์ชันสะสมปัจจุบันและรายการปัจจุบันของรายการ ฟังก์ชันใดก็ตามที่ส่งคืนจะกลายเป็นตัวสะสมใหม่ซึ่งจะถูกส่งผ่านไปยังฟังก์ชันในครั้งต่อไป นี่คือวิธีที่คุณ "จดจำ" ค่าเมื่อคุณวนลูป FP-style ฉันให้ฟังก์ชั่นที่ใช้ 2 ตัวเลขและเพิ่มเข้าไป
นี่คือการสะสมเริ่มต้น; สิ่งที่แอคคูมูเลเตอร์จะเริ่มต้นเหมือนก่อนที่รายการใด ๆ ในรายการจะถูกประมวลผล เมื่อคุณรวมตัวเลขจำนวนรวมก่อนที่คุณจะเพิ่มตัวเลขเข้าด้วยกันคืออะไร 0 ซึ่งฉันผ่านเป็นอาร์กิวเมนต์ที่สอง
สุดท้ายเช่นเดียวกับแผนที่เรายังผ่านรายการหมายเลขเพื่อให้ดำเนินการ
หากการพับยังคงไม่สมเหตุสมผลโปรดพิจารณาสิ่งนี้ เมื่อคุณเขียน:
# Notice I passed the plus operator directly this time,
# instead of wrapping it in another function.
fold(+, 0, numbers)
คุณจะใส่ฟังก์ชั่นที่ส่งผ่านระหว่างแต่ละรายการในรายการและเพิ่มการสะสมเริ่มต้นไปทางซ้ายหรือขวา (ขึ้นอยู่กับว่ามันเป็นการพับซ้ายหรือขวา) ดังนั้น:
[1, 2, 3, 4, 5]
กลายเป็น:
0 + 1 + 2 + 3 + 4 + 5
^ Note the initial accumulator being added onto the left (for a left fold).
ซึ่งเท่ากับ 15
ใช้ a map
เมื่อคุณต้องการเปลี่ยนหนึ่งรายการเป็นรายการอื่นที่มีความยาวเท่ากัน
ใช้ a fold
เมื่อคุณต้องการเปลี่ยนรายการเป็นค่าเดียวเช่นการรวมรายการตัวเลข
ในฐานะที่เป็น @Jorg ชี้ให้เห็นในความคิดเห็นแม้ว่า "ค่าเดียว" ไม่จำเป็นต้องเป็นสิ่งที่ง่ายเหมือนจำนวน; มันอาจเป็นวัตถุใด ๆ ก็ได้รวมถึงรายการหรือสิ่งอันดับ! วิธีที่ฉันมีโฟลเดคลิกจริงสำหรับฉันคือการกำหนดแผนที่ในรูปของการพับ สังเกตว่ารายการเป็นตัวสะสมอย่างไร:
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)
เมื่อคุณเข้าใจในความจริงแล้วคุณจะรู้ว่าเกือบทุกการวนซ้ำสามารถถูกแทนที่ด้วยการพับหรือแผนที่