ควรใช้ภาษาการเขียนโปรแกรมเชิงฟังก์ชันเมื่อใด


90

ในสถานการณ์ใดที่ฉันควรเลือกใช้ภาษาโปรแกรมที่ใช้งานได้กับภาษาเชิงวัตถุแบบละเอียดเช่น C ++, C # หรือ Java

ฉันเข้าใจว่าการเขียนโปรแกรมเชิงฟังก์ชันคืออะไรสิ่งที่ฉันไม่เข้าใจจริงๆคือปัญหาประเภทใดจึงเป็นทางออกที่สมบูรณ์แบบ?


คำถามนี้มีคำตอบที่นี่stackoverflow.com/questions/381685/…
krosenvold

2
เสมอ. หรืออย่างน้อยก็ไม่เคย
Shelby Moore III

1
ด้วย lambdas C # คือการทำงานของเส้นเขตแดน
JD

คำตอบ:


51

ในความคิดของฉันภาษาที่ใช้งานได้ดีสำหรับสองสิ่งหลัก ๆ คือ AI เกมและการคำนวณทางคณิตศาสตร์ เป็นสิ่งที่ดีในเกม AIs เนื่องจากมีการปรับแต่งรายการที่ดี (อย่างน้อยใน Lisp และ Scheme) และสำหรับการคำนวณทางคณิตศาสตร์เนื่องจากไวยากรณ์ของมัน Scheme, Lisp และ Haskell มีไวยากรณ์ที่ทำให้การคำนวณทางคณิตศาสตร์ง่ายต่อการอ่าน สิ่งสุดท้ายที่ฉันต้องเพิ่มคือภาษาที่ใช้งานได้เป็นภาษาที่สนุกมาก หลักสูตรโครงการของฉันเป็นหนึ่งในหลักสูตรที่ฉันสนุกที่สุด


2
หลังจากที่ฉันเข้าใจความจริงที่ว่าสมองของฉันอยากจะระเบิดในสัปดาห์แรกของชั้นเรียนคอมไพเลอร์ที่ฉันเข้าร่วมโครงการฉันก็พบว่ามันสนุกมาก (และฉันก็ดีขึ้นมากฮิฮิ)
Alex Baranosky

1
คุณใช้ภาษาที่ใช้ในการคำนวณทางคณิตศาสตร์ใดบ้าง
Jules

8
คอมไพเลอร์ด้วย! ฉันเคยได้ยินคนที่เขียนคอมไพเลอร์ใน Haskell บอกว่าพวกเขาจะ "ไม่เขียนคอมไพเลอร์ในภาษาที่จำเป็นอีกแล้ว"
ShreevatsaR

1
julesjacobs: ฉันใช้ทั้ง haskell และ Scheme เล็กน้อยเพื่อแก้ปัญหาการคำนวณทางคณิตศาสตร์อย่างง่าย ฉันไม่เก่งภาษาเหล่านั้นเลยฉันจึงมีวิธีแก้ไขปัญหาที่ซับซ้อนมากขึ้น ฉันไม่สามารถทำให้พวกเขาเร็วพอในตอนนี้
Martiert

96

ฉันได้ทำการค้นคว้าเกี่ยวกับเรื่องนี้ด้วยตัวเองและคิดว่าฉันอาจเพิ่ม CONCURRENCY ลงในรายการเหตุผลในการใช้ภาษาที่ใช้งานได้ ดูว่าในบางจุดความเร็วโปรเซสเซอร์ในอนาคตอันใกล้จะไม่สามารถเพิ่มขึ้นได้โดยใช้เทคโนโลยี cpu เดียวกัน ฟิสิกส์ของสถาปัตยกรรมไม่ยอมให้ทำ

นั่นคือที่มาของการประมวลผลพร้อมกัน

น่าเสียดายที่ภาษา OOP ส่วนใหญ่ไม่สามารถใช้ประโยชน์จากโปรเซสเซอร์หลายตัวพร้อมกันได้เนื่องจากการพึ่งพาซึ่งกันและกันระหว่างข้อมูล

ในภาษาโปรแกรมที่ใช้งานได้จริงคอมพิวเตอร์สามารถเรียกใช้ฟังก์ชันสองฟังก์ชัน (หรือมากกว่านั้น) พร้อมกันได้เนื่องจากฟังก์ชันเหล่านี้ไม่ได้เปลี่ยนแปลงข้อมูลสถานะภายนอก

นี่คือบทความที่ยอดเยี่ยมเกี่ยวกับการเขียนโปรแกรมเชิงฟังก์ชันที่คุณอาจชอบ


38
ฉันจะไม่บอกว่าภาษา OO ส่วนใหญ่ไม่สามารถใช้ประโยชน์จากโปรเซสเซอร์จำนวนมากโดยพลการ ฉันจะบอกว่าสำหรับโปรแกรมที่จะใช้ประโยชน์จากโปรเซสเซอร์หลายตัวในเวลาเดียวกันอย่างมีประสิทธิภาพและเชื่อถือได้โปรแกรมนั้นจะต้องได้รับการจัดระเบียบให้หน่วยโค้ดที่เน้นการคำนวณส่วนใหญ่ทำงานเหมือนฟังก์ชันบริสุทธิ์ เป็นไปได้ที่จะจัดโปรแกรมในลักษณะนั้นในภาษาส่วนใหญ่ การทำในภาษาที่ใช้งานได้ง่ายกว่าภาษาที่จำเป็น (รวมถึงภาษาเชิงวัตถุ)
Zak

2
ขอบคุณสำหรับการเชื่อมโยงบทความนั้น มันช่วยอธิบายสิ่งต่างๆให้ฉันได้จริงๆ
abc123

13

เพื่อนคนหนึ่งของฉันอ้างถึงอาจารย์ในวิทยาลัยของเขาคนหนึ่งว่า:

วาดเส้นตารางที่มีชนิดข้อมูลอยู่ด้านบนและดำเนินการกับประเภทข้อมูลเหล่านั้นทางด้านซ้าย ถ้าคุณตัดตารางในแนวตั้งแสดงว่าคุณกำลังทำ OO ถ้าคุณตัดกริดในแนวนอนแสดงว่าคุณกำลังทำ FP

คำตอบของฉันคือ FP เป็นวิธีการเขียนโปรแกรมที่ใช้งานได้อย่างสมบูรณ์โดยมีแอปพลิเคชันที่หลากหลายพอ ๆ ฉันคิดว่าคำถามที่สำคัญกว่าคือ:

  1. คุณมีเวลาลงทุนในการเรียนรู้สัญกรณ์ใหม่และวิธีคิดใหม่ ๆ หรือไม่?
  2. ภาษาใดที่คุณกำลังพิจารณาว่ามีไลบรารีที่สมบูรณ์เพียงพอที่คุณจะไม่ติดขัดในการคิดค้นนวัตกรรมใหม่ ๆ

สำหรับคำถามแรกหากคุณทำสิ่งนี้เพื่อประโยชน์ในการเรียนรู้เป็นหลักฉันขอแนะนำให้ดูที่Haskellเนื่องจากมีสื่อสนับสนุนมากมาย (หนังสือบทความชุมชนที่ใช้งานอยู่ ฯลฯ )

สำหรับคำถามที่สอง Haskell มีไลบรารีที่หลากหลาย (แม้ว่าบางแห่งจะโตกว่าคนอื่น ๆ ) แต่Scala (ภาษาที่ใช้งาน OO แบบไฮบริดที่ทำงานบน JVM) มีข้อดีที่คุณสามารถค่อยๆเปลี่ยนไปใช้รูปแบบการทำงานได้มากขึ้น และคุณมีไลบรารี Java ที่เข้าถึงได้ทั้งหมดสำหรับคุณ


ฉันเรียนโครงการ Scheme ในวิทยาลัยดังนั้นฉันจึงไม่ต้องการเรียนรู้การเขียนโปรแกรมเชิงฟังก์ชันเพียงเพื่อประสบการณ์ ฉันอยากจะเรียนรู้ภาษาที่ใช้งานได้จริงด้วยเหตุผลในทางปฏิบัติ
Alex Baranosky

9

ในทางปฏิบัติทุกอย่างที่คุณสามารถทำได้ใน PP สามารถทำได้ใน FP และสิ่งเดียวกันในทางกลับกัน เป็นอีกวิธีหนึ่งในการเขียนโค้ดบางอย่างซึ่งเป็นอีกมุมมองหนึ่งของปัญหาและวิธีอื่นในการแก้ไข

อย่างไรก็ตามเนื่องจากมีคนไม่มากที่ใช้ FP ปัญหาจึงเป็นเรื่องของการขาดไลบรารีที่ดีความสามารถในการพกพา / การบำรุงรักษา (เนื่องจากผู้ดูแลมีโอกาสที่จะเข้าใจสิ่งที่เขียนใน C ++ มากกว่า Scheme) และการขาดเอกสารและชุมชน ฉันรู้ว่ามีเอกสารบางอย่างอย่างไรก็ตามเปรียบเทียบกับ C ++, C # หรือ Java แล้วคุณจะเข้าใจว่าฉันหมายถึงอะไร

อย่างไรก็ตามหากคุณต้องการทำ FP จริงๆคุณสามารถใช้ลักษณะนี้ได้แม้ใน C ++ และ C # แน่นอนว่ามันจะไม่ใช่ FP 100% หากคุณใช้ไลบรารีมาตรฐาน น่าเสียดายที่ฉันไม่คิดว่า C # ได้รับการปรับให้เหมาะกับการใช้งานการเขียนโปรแกรมและอาจสร้างปัญหาด้านประสิทธิภาพมากมาย

นี่เป็นโพสต์ส่วนตัวมากกว่าสิ่งที่ฉันคิดเกี่ยวกับ FP ไม่ใช่การประกาศอย่างเข้มงวด


8
"ทุกอย่างในทางปฏิบัติคุณสามารถทำได้ใน PP สามารถทำได้ใน FP" - ที่จริงก็คือว่าทุกอย่าง
BlueRaja - Danny Pflughoeft

2
@BlueRaja - คุณหมายถึงความสมบูรณ์ของ Turing หรือไม่? ถ้าเป็นเช่นนั้นสิ่งที่คุณพูดจะไม่เป็นไปตามนั้น ตัวอย่างเช่นเกมชีวิตของ Conway เป็นเกม Turing Complete แต่คุณไม่สามารถใช้เพื่อเขียนไดรเวอร์การ์ดแสดงผลได้อย่างที่คุณทำได้ใน C ฉันไม่เห็นเกมล่าสุดที่เขียนใน Haskell สามารถทำได้ใน FP! = ในทางทฤษฎีสามารถทำได้ใน FP เชิงทฤษฎี
Luigi Plinge

@ Luigi Plinge ฉันต้องเห็นด้วยกับ BlueRaja Haskellers พูดคุยเกี่ยวกับไดรเวอร์ Linux บางตัวที่เขียนใน Haskell ฉันไม่มีลิงค์ แต่ยังได้ยินว่ามีการเขียนระบบปฏิบัติการใน Haskell (ภาษาที่ใช้งานได้อื่น ๆ ด้วย) เท่าที่ผ่านมาฉันไม่เห็นเกมล่าสุดที่เขียนด้วย C # หรือ Java คุณหมายความว่าพวกเขาไม่สามารถใช้สำหรับสิ่งนั้นได้หรือไม่? อย่างไรก็ตามตัวอย่างเกมที่เขียนด้วย FP นอกจากนี้โปรดทราบว่าลิงก์ส่วนใหญ่ของฉันคือ Haskell ซึ่งเป็นภาษาที่ใช้งานได้จริง
austinprete

@PardonMyRhetoric เห็นได้ชัดว่าคุณสามารถเขียนเกมใน Haskell และทำการคำนวณใด ๆ ได้ แต่ความเร็วจะช้าลงหลายเท่าและใช้หน่วยความจำสูงขึ้น ดังนั้นตัวอย่างที่สวนทางกับคำสั่งของ BlueRaja ก็คือคุณไม่สามารถเขียน "เกมที่เร็วเท่าและใช้หน่วยความจำมากเท่ากับ C" ใน FP นี่เป็นปัญหาในทางปฏิบัติที่แท้จริงไม่ใช่เคล็ดลับการอวดดี (และฉันไม่ได้ออกไปทุบ FP เลย - ตอนนี้ฉันกำลังเขียนโค้ด Scala!)
Luigi Plinge

1
@PardonMyRhetoric มันต้องเป็นสำนวน FP ด้วย เกณฑ์มาตรฐานที่คุณเห็นว่าให้ประสิทธิภาพของ Haskell ใกล้เคียงกับ C นั้นเขียนในรูปแบบเดียว "ระดับต่ำ" ซึ่งโปรแกรมเมอร์ของ Haskell ส่วนใหญ่ไม่สามารถเขียนได้ ตัวอย่างเช่นคุณสามารถบรรลุประสิทธิภาพที่คล้ายกันได้โดยเพียงแค่สร้างเอาต์พุตโค้ด Haskell และคอมไพล์โค้ด C ไม่มีจุดหมายแม้ว่า ปัญหาในทางปฏิบัติที่เกี่ยวข้องคือสิ่งที่ "คุณทำได้" กับสิ่งที่ "ทำได้ / ทำได้" หากสิ่งที่ยากเกินไปก็ไม่สำคัญมากนักหากเป็นไปได้ในทางทฤษฎี (และ "เป็นไปได้" สำหรับใคร)
Luigi Plinge

4

ภาษาที่ใช้งานได้ดีในหลาย ๆ สถานการณ์ ขึ้นอยู่กับไลบรารีของภาษาที่ใช้งานได้เฉพาะ

คุณจะตอบคำถาม "เมื่อใดควรใช้ภาษาโปรแกรมเชิงวัตถุ"?


1
"เมื่อใดควรใช้ภาษาโปรแกรมเชิงวัตถุ" เมื่อคุณต้องการสร้างแบบจำลองการคำนวณในทางกลับกันฉันกำลังมองหาปัญหาที่ fp จะเป็นคำตอบที่ใช้งานง่ายฉันยังคงมองหานั่นคือวิธีที่ฉันพบโพสต์นี้
jimjim

@Arjang ฉันเดาว่าการเขียนโปรแกรมเชิงฟังก์ชันจะพบการใช้งานอย่างมากในแอปพลิเคชันการคำนวณที่ต้องการเพียงอินพุตเพื่อสร้างเอาต์พุต ไม่มีความ
ผิดเพี้ยน

3

แม้ว่านี่จะเป็นค่อนข้างคำถามอัตนัยฉันต้องการเพียงเพื่อเพิ่มว่าภาษาที่จะใช้ในการทำงานจำนวนมากที่จะแยกวิเคราะห์ภาษาเฉพาะโดเมน ; ลักษณะการทำงานช่วยให้สามารถแยกวิเคราะห์ไวยากรณ์ได้ดี


2
กำลังแยกวิเคราะห์ DSL? ฉันคิดว่าด้วยมาโคร Lisp และในทำนองเดียวกัน DSL จะถูกนำไปใช้เป็นมาโครไม่ใช่สิ่งที่โปรแกรม Lisp จะแยกวิเคราะห์ YMMV กับภาษาที่ไม่ใช่ Lisp :-P
Chris Jester-Young

1

จากสิ่งที่ฉันเห็นมันเป็นเรื่องของรสนิยมมากกว่าฟังก์ชั่นการใช้งาน (ไม่ได้ตั้งใจเล่น) ไม่มีอะไรเกี่ยวกับรูปแบบของภาษาที่ทำให้งานเฉพาะเจาะจงดีขึ้นหรือแย่ลง


2
@JonHarrop - สนใจที่จะอธิบายอย่างละเอียดว่า? ฉันไม่เห็นว่ามันชัดเจนนักและมันจะน่าเสียดายถ้าคุณทิ้งความประทับใจที่คุณโหวตให้คนอื่นออกไปจาก meer boosterisim
TED

1
กลุ่มภาษา ML ได้รับการอบรมมาโดยเฉพาะสำหรับการเขียนโปรแกรมด้วยการเพิ่มคุณสมบัติของภาษาที่ซับซ้อนเช่นการจับคู่รูปแบบสำหรับการจัดการกับต้นไม้ (เช่นต้นไม้นิพจน์) ดังนั้นภาษาตระกูลนี้จึงดีกว่ามากในงานเฉพาะนั้น
JD

1
@JonHarrop - ฉันจะยอมรับมัน อย่างไรก็ตามคุณกำลังพูดถึง ML ไม่ใช่ภาษาที่ใช้งานได้โดยทั่วไป ฉันเชื่อใน DSL เป็นอย่างมากดังนั้นฉันจะไม่โต้แย้งการใช้ภาษาเฉพาะสำหรับงานที่ออกแบบมาสำหรับ
TED

ปัจจุบันการจับคู่รูปแบบพบได้ในภาษาที่ใช้งานได้เกือบทั้งหมดรวมถึง OCaml, F #, Scala, Haskell, Clojure และ Erlang ตัวอย่างเช่นเมื่อเร็ว ๆ นี้ฉันได้สร้างกลไกกฎทางธุรกิจสำหรับลูกค้าที่เน้นคณิตศาสตร์ นั่นคือ F # 1,000 บรรทัดและส่วนใหญ่เป็นล่าม Lexing การแยกวิเคราะห์การตรวจสอบประเภทและการตีความข้อมูลทั้งหมดนั้นง่ายกว่ามากด้วยการจับคู่รูปแบบ
JD

@JonHarrop .. แต่ไม่ใช่ทั้งหมด ไม่ใช่คุณลักษณะโดยธรรมชาติของภาษาที่ใช้งานได้ซึ่งเป็นคำถามที่ถามเกี่ยวกับ
TED

1

โดยทั่วไปให้ใช้ภาษาที่ง่ายที่สุดในการแสดงวิธีแก้ปัญหา สำหรับการเขียนโปรแกรมเชิงฟังก์ชันนี่คือเมื่อการแก้ปัญหานั้นแสดงออกมาในรูปของฟังก์ชันได้อย่างง่ายดายดังนั้นชื่อ โดยทั่วไปจะดีสำหรับการดำเนินการทางคณิตศาสตร์ AI การจับคู่รูปแบบ โดยทั่วไปสิ่งที่สามารถแบ่งออกเป็นชุดของกฎที่ต้องใช้เพื่อให้ได้คำตอบ คุณสามารถกำหนดภาษาที่ "ดีที่สุด" ที่จะใช้หลังจากที่คุณวิเคราะห์ปัญหาของคุณได้เพียงพอแล้ว นี่คือจุดที่รหัสหลอกมีประโยชน์ หากคุณพบว่าตัวเองกำลังเขียนโค้ดหลอกที่ดูเหมือน FP ให้ใช้ FP

แน่นอนว่าภาษาการเขียนโปรแกรมที่สมบูรณ์ทั้งหมดมีฟังก์ชันเทียบเท่ากันดังนั้นจึงไม่สำคัญว่าคุณจะเลือกภาษาใดในแง่ของปัญหาที่คุณสามารถแก้ไขได้ ผลกระทบหลักจะอยู่ในแง่ของประสิทธิภาพและความแม่นยำในการเข้ารหัสและความสะดวกในการบำรุงรักษา

โปรดทราบว่าเป็นไปได้ที่จะเลียนแบบ FP ภายในภาษา OO ผ่าน API ที่ออกแบบมาอย่างชาญฉลาด ตัวอย่างเช่นฉันเคยเห็นไลบรารี Java จำนวนมาก (JMock เป็นตัวอย่างหนึ่ง) ที่ใช้วิธีการผูกมัดเพื่อจำลอง FP DSL จากนั้นคุณจะเห็นโครงสร้างเช่น:

logger.expects(once()).method("error") .with( and(stringContains(action),stringContains(cause)) );

โดยพื้นฐานแล้วจะสร้างฟังก์ชันที่ได้รับการประเมินเพื่อพิจารณาว่าลำดับการเรียกบนวัตถุจำลองนั้นถูกต้องหรือไม่ (ตัวอย่างที่ขโมยมาจากhttp://www.jmock.org/yoga.html )

ไวยากรณ์คล้าย FP ในภาษา OO อื่นคือการใช้การปิดเช่นใน Ruby


2
"... ไม่สำคัญว่าคุณจะเลือกแบบไหนในแง่ของปัญหาที่คุณสามารถแก้ไขได้" เฉพาะในกรณีที่คุณมีเวลาและเงินไม่ จำกัด ในการแก้ปัญหาของคุณ
JD

0

ฉันคิดว่าโพสต์ก่อนหน้านี้ถูกต้องนี่เป็นรายการสั้น ๆ การเขียนโปรแกรมเชิงฟังก์ชันเป็นโซลูชันที่สมบูรณ์แบบสำหรับสิ่งต่อไปนี้:

  • การประมวลผลแบบไร้สัญชาติ
  • สมการทางคณิตศาสตร์รวมถึง ML (Machine Learning)
  • กระบวนการที่ไม่เปลี่ยนรูป
  • เมื่อคุณต้องการการทำงานพร้อมกันที่ปรับขนาดได้
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.