Combinators คืออะไร
ฉันกำลังหา:
- คำอธิบายการปฏิบัติ
- ตัวอย่างการใช้งาน
- ตัวอย่างของวิธีการที่ combinators ปรับปรุงคุณภาพ / รหัสทั่วไป
ฉันไม่ได้กำลังมองหา:
- คำอธิบายของ combinators ที่ไม่ได้ช่วยให้ฉันทำงานเสร็จ (เช่น Y-combinator)
Combinators คืออะไร
ฉันกำลังหา:
ฉันไม่ได้กำลังมองหา:
คำตอบ:
จาก combinators มุมมองที่เป็นประโยชน์เป็นชนิดของการเขียนโปรแกรมสร้างที่ช่วยให้คุณรวบรวมชิ้นส่วนของตรรกะในมารยาทที่น่าสนใจและมักจะสูง โดยทั่วไปแล้วการใช้พวกมันขึ้นอยู่กับความเป็นไปได้ของความสามารถในการแพ็คโค้ดที่สามารถใช้งานได้ลงในวัตถุซึ่งมักจะเรียกว่า (สำหรับเหตุผลทางประวัติศาสตร์) ฟังก์ชั่นแลมบ์ดาหรือการแสดงออกแลมบ์ดา
ตัวอย่างง่ายๆของ combinator (มีประโยชน์) คือฟังก์ชั่นแลมบ์ดาสองฟังก์ชั่นที่ไม่มีพารามิเตอร์และสร้างฟังก์ชันใหม่ตามลำดับ Combinator ที่แท้จริงมีลักษณะเป็น pseudocode ทั่วไปดังนี้:
func in_sequence(first, second):
lambda ():
first()
second()
สิ่งสำคัญที่ทำให้ combinator นี้เป็นฟังก์ชั่นนิรนาม (ฟังก์ชั่นแลมบ์ดา) ในบรรทัดที่สอง; เมื่อคุณโทร
a = in_sequence(f, g)
วัตถุที่เป็นผลลัพธ์ a ไม่ใช่ผลลัพธ์ของการเรียกใช้ f () ก่อนแล้วจึง g () แต่เป็นวัตถุที่คุณสามารถเรียกใช้ในภายหลังเพื่อดำเนินการ f () และ g () ตามลำดับ:
a() // a is a callable object, i.e. a function without parameters
คุณสามารถมี combinator ที่รันโค้ดบล็อกสองชุดในเวลาเดียวกันในทำนองเดียวกัน:
func in_parallel(first, second):
lambda ():
t1 = start_thread(first)
t2 = start_thread(second)
wait(t1)
wait(t2)
แล้วอีกครั้ง
a = in_parallel(f, g)
a()
สิ่งที่เจ๋งคือ 'in_parallel' และ 'in_sequence' เป็นทั้ง combinators ที่มีประเภท / ลายเซ็นเหมือนกันนั่นคือพวกเขาทั้งสองใช้วัตถุฟังก์ชันไร้พารามิเตอร์สองตัวและส่งคืนวัตถุใหม่ จริงๆคุณสามารถเขียนสิ่งต่าง ๆ เช่น
a = in_sequence(in_parallel(f, g), in_parallel(h, i))
และทำงานได้ตามที่คาดไว้
โดยพื้นฐานแล้วผู้ประสานจะอนุญาตให้คุณสร้างโฟลว์การควบคุมของโปรแกรม (เหนือสิ่งอื่นใด) ในขั้นตอนและยืดหยุ่น ตัวอย่างเช่นหากคุณใช้ combinator in_parallel (.. ) เพื่อเรียกใช้ parallelism ในโปรแกรมของคุณคุณสามารถเพิ่มการดีบักที่เกี่ยวข้องกับการใช้งานของ in_parallel combinator ได้ หลังจากนั้นหากคุณสงสัยว่าโปรแกรมของคุณมีข้อผิดพลาดเกี่ยวกับการขนานคุณสามารถนำมาใช้ใหม่ได้ใน in_parallel:
in_parallel(first, second):
in_sequence(first, second)
และด้วยหนึ่งจังหวะส่วนที่ขนานทั้งหมดได้รับการแปลงเป็นลำดับ!
Combinators มีประโยชน์มากเมื่อใช้งานถูกต้อง
อย่างไรก็ตาม Combinator Y ไม่จำเป็นต้องใช้ในชีวิตจริง มันเป็นคอมบิเนเตอร์ที่ให้คุณสร้างฟังก์ชั่นแบบเรียกซ้ำได้เองและคุณสามารถสร้างมันได้อย่างง่ายดายในภาษาสมัยใหม่ใด ๆ โดยไม่ต้องคอมบิเนเตอร์ Y
มันผิดที่แบรนด์ Y-combinator เป็นสิ่งที่ไม่ "ช่วยให้งานเสร็จ" ฉันพบว่ามันมีประโยชน์มากในหลายโอกาส กรณีที่ชัดเจนที่สุดคือเมื่อคุณต้องบู๊ตภาษาที่แปลแล้วแบบฝัง ถ้าคุณให้ชุดที่น้อยที่สุดของวิทยาการคือsequence
, select
, call
, const
และclosure allocation
มันมีอยู่แล้วเพียงพอสำหรับการสร้างที่สมบูรณ์ภาษาที่ซับซ้อนโดยพลการ ไม่ต้องการการสนับสนุนพิเศษสำหรับการเรียกซ้ำ - สามารถเพิ่มผ่าน combinator จุดคงที่ มิฉะนั้นคุณจะต้องใช้วิธีการที่ซับซ้อนกว่าเดิมมาก
อีกกรณีที่ชัดเจนสำหรับ combinators คือ obfuscation รหัสที่แปลเป็นแคลคูลัส SKI นั้นอ่านไม่ได้ในทางปฏิบัติ หากคุณจริงๆต้องงงงวยการดำเนินการตามขั้นตอนวิธีพิจารณาใช้ combinators, นี่คือตัวอย่าง
และแน่นอนว่า combinators เป็นเครื่องมือสำคัญในการใช้ภาษาที่ใช้งานได้ วิธีที่ง่ายที่สุด (ตามตัวอย่างข้างต้น) คือผ่าน SKI หรือแคลคูลัสที่เทียบเท่า Supercombinatorsถูกนำมาใช้ในการใช้งานอื่น ๆ หนังสือเล่มนี้พูดถึงมันในเชิงลึก
นี่เป็นเรื่องตลกแต่เป็นเรื่องตลกที่ควรค่าแก่การอ่านอย่างละเอียดเนื่องจากมีเทคนิคและทฤษฎีการเขียนโปรแกรมแบบอาร์เคนจำนวนมาก
ฉันพบคำถาม StackOverflow คำอธิบายที่ดีของ“ Combinators” (สำหรับผู้ที่ไม่ใช่นักคณิตศาสตร์)นั่นเป็นลูกพี่ลูกน้องของคำถามนี้ หนึ่งในคำตอบที่ชี้ไปยังบล็อกของ Homaliconic ของ Reginald Braithwaiteซึ่งเชื่อมโยงไปยังตัวอย่างที่มีประโยชน์หลายอย่างของ combinators ในรหัส (เช่นK combinator ที่ใช้โดยObject#tap
วิธีของ Ruby - อ่านหน้าเพื่อดูตัวอย่างว่าทำไมจึงมีประโยชน์)
หน้าวิกิพีเดียลอจิก Combinatoryอธิบาย combinators มากขึ้นทั่วโลก