แคลคูลัสแลมบ์ดาเป็นรูปแบบการคำนวณที่คิดค้นโดยโบสถ์อลองโซในยุค 30 ไวยากรณ์และความหมายของภาษาโปรแกรมส่วนใหญ่นั้นได้รับแรงบันดาลใจโดยตรงหรือโดยอ้อมจากแคลคูลัสแลมบ์ดา
แคลคูลัสแลมบ์ดาในรูปแบบพื้นฐานที่สุดมีสองการดำเนินการ: นามธรรม (การสร้างฟังก์ชั่น (ไม่ระบุชื่อ)) และแอปพลิเคชัน (ใช้ฟังก์ชั่น) Abstraction ดำเนินการโดยใช้โอเปอเรเตอร์ giving โดยให้แลมบ์ดาแคลคูลัสชื่อ
- นิพจน์แลมบ์ดา
- ฟังก์ชั่นแลมบ์ดา
ฟังก์ชั่นที่ไม่ระบุชื่อมักจะถูกเรียกว่า "lambdas", "ฟังก์ชั่นแลมบ์ดา" หรือ "การแสดงออกแลมบ์ดา" เพราะที่ผมกล่าวข้างต้นλเป็นสัญลักษณ์ในการสร้างฟังก์ชั่นที่ไม่ระบุชื่อในแคลคูลัสแลมบ์ดา (และคำlambda
ที่ใช้ในการสร้างฟังก์ชั่นที่ไม่ระบุชื่อในหลายกระเพื่อม ภาษาที่ใช้ด้วยเหตุผลเดียวกัน)
นี่ไม่ใช่คำศัพท์ที่ใช้กันทั่วไป แต่ฉันคิดว่ามันหมายถึงการเขียนโปรแกรมโดยใช้ฟังก์ชั่นที่ไม่ระบุชื่อหรือการเขียนโปรแกรมโดยใช้ฟังก์ชั่นที่สูงกว่า
ข้อมูลเพิ่มเติมเกี่ยวกับ lambdas ใน C ++ 0x แรงจูงใจของพวกเขาและวิธีการที่เกี่ยวข้องกับพอยน์เตอร์ฟังก์ชั่น (ส่วนมากนี่อาจเป็นการทำซ้ำสิ่งที่คุณรู้อยู่แล้ว แต่ฉันหวังว่ามันจะช่วยอธิบายแรงจูงใจของ lambdas จากตัวชี้ฟังก์ชั่น):
พอยน์เตอร์ของฟังก์ชั่นซึ่งมีอยู่แล้วใน C นั้นมีประโยชน์มากเช่นส่งผ่านฟังก์ชั่นการเปรียบเทียบไปยังฟังก์ชั่นการเรียงลำดับ อย่างไรก็ตามมีข้อ จำกัด ในการใช้ประโยชน์ของพวกเขา:
ตัวอย่างเช่นหากคุณต้องการเรียงลำดับเวกเตอร์ของเวกเตอร์ตามi
องค์ประกอบที่สามของแต่ละเวกเตอร์ (โดยที่i
พารามิเตอร์เวลาทำงาน) คุณไม่สามารถแก้ไขสิ่งนี้ด้วยตัวชี้ฟังก์ชัน ฟังก์ชั่นที่เปรียบเทียบสองเวกเตอร์โดยi
องค์ประกอบที่สามของพวกเขาจะต้องใช้เวลาสามข้อโต้แย้ง ( i
และทั้งสองเวกเตอร์) แต่ฟังก์ชั่นการเรียงลำดับจะต้องฟังก์ชั่นการใช้สองข้อโต้แย้ง สิ่งที่เราต้องการคือวิธีส่งอาร์กิวเมนต์i
ไปยังฟังก์ชันก่อนส่งผ่านไปยังฟังก์ชันการเรียงลำดับ แต่เราไม่สามารถทำได้ด้วยฟังก์ชัน C ธรรมดา
เพื่อแก้ปัญหานี้ C ++ ได้แนะนำแนวคิดของ "function objects" หรือ "functors" functor นั้นเป็นวัตถุที่มีoperator()
วิธีการ ตอนนี้เราสามารถกำหนดคลาสCompareByIthElement
ซึ่งรับอาร์กิวเมนต์i
เป็นอาร์กิวเมนต์คอนสตรัคเตอร์จากนั้นนำเวกเตอร์สองตัวมาเปรียบเทียบเป็นอาร์กิวเมนต์กับoperator()
เมธอด ในการจัดเรียงเวกเตอร์ของเวกเตอร์ด้วยi
องค์ประกอบที่สามตอนนี้เราสามารถสร้างCompareByIthElement
วัตถุi
ที่มีอาร์กิวเมนต์แล้วผ่านวัตถุนั้นไปยังฟังก์ชันการเรียงลำดับ
เนื่องจากฟังก์ชั่นวัตถุเป็นเพียงวัตถุและไม่ใช่ฟังก์ชั่นทางเทคนิค (แม้ว่าวัตถุเหล่านั้นจะทำตัวเหมือนพวกมัน) คุณจึงไม่สามารถสร้างตัวชี้ฟังก์ชั่นชี้ไปที่วัตถุฟังก์ชันได้ (แน่นอนว่าคุณสามารถมีตัวชี้ไปยังวัตถุฟังก์ชันได้ จะมีประเภทที่ชอบCompareByIthElement*
และจึงไม่เป็นตัวชี้ฟังก์ชั่น)
ฟังก์ชั่นส่วนใหญ่ในไลบรารีมาตรฐาน C ++ ซึ่งรับฟังก์ชั่นเป็นอาร์กิวเมนต์จะถูกกำหนดโดยใช้เทมเพลตเพื่อให้ทำงานกับพอยน์เตอร์ของฟังก์ชั่นเช่นเดียวกับฟังก์ชั่นวัตถุ
ตอนนี้เพื่อ lambdas:
การกำหนดคลาสทั้งหมดเพื่อเปรียบเทียบโดยi
องค์ประกอบ th เป็นบิตอย่างละเอียดถ้าคุณจะใช้มันเพียงครั้งเดียวเพื่อจัดเรียงเวกเตอร์ แม้ในกรณีที่คุณต้องการเพียงแค่ตัวชี้ฟังก์ชันการกำหนดฟังก์ชั่นที่ตั้งชื่อนั้นเหมาะสมที่สุดหากใช้เพียงครั้งเดียวเพราะก) มันทำให้เกิดมลภาวะต่อเนมสเปซและ b) ฟังก์ชั่นมักจะมีขนาดเล็กมาก เหตุผลที่ดีในการสรุปตรรกะลงในฟังก์ชั่นของตัวเอง (นอกเหนือจากที่คุณไม่สามารถมีตัวชี้ฟังก์ชั่นโดยไม่ต้องกำหนดฟังก์ชั่น)
ดังนั้นเพื่อแก้ไข lambdas นี้ถูกนำเสนอ แลมบ์ดาเป็นวัตถุฟังก์ชันไม่ใช่พอยน์เตอร์ของฟังก์ชัน หากคุณใช้แลมบ์ดาตัวอักษรเช่น[x1, x2](y1,y2){bla}
รหัสถูกสร้างขึ้นซึ่งโดยทั่วไปจะทำต่อไปนี้:
- กำหนดระดับซึ่งมีตัวแปรสมาชิกสอง (ก
x1
และx2
) และoperator()
มีการขัดแย้ง ( y1
และy2
) bla
และร่างกาย
- สร้างอินสแตนซ์ของคลาสการตั้งค่าตัวแปรสมาชิก
x1
และx2
ค่าของตัวแปรx1
และx2
อยู่ในขอบเขต
ดังนั้นแลมบ์ดาจึงทำตัวเหมือนฟังก์ชั่นวัตถุยกเว้นว่าคุณไม่สามารถเข้าถึงคลาสที่สร้างขึ้นเพื่อนำแลมบ์ดาไปใช้ในทางอื่นนอกจากใช้แลมบ์ดา ดังนั้นฟังก์ชั่นใด ๆ ที่ยอมรับฟังก์ชั่นเป็นอาร์กิวเมนต์ (โดยทั่วไปหมายถึงฟังก์ชั่นที่ไม่ใช่ C ใด ๆ ในไลบรารีมาตรฐาน) จะยอมรับ lambdas แต่ฟังก์ชั่นใด ๆ ที่ยอมรับเฉพาะพอยน์เตอร์ฟังก์ชั่นจะไม่