บางทีคุณอาจเพิ่งเคยได้ยินเกี่ยวกับ Functional Programming และมีคำถามบางอย่าง
ชอบ…
- การเขียนโปรแกรมเชิงฟังก์ชันคืออะไรกันแน่?
- เปรียบเทียบกับการเขียนโปรแกรมเชิงวัตถุเป็นอย่างไร
- คุณควรใช้การเขียนโปรแกรมเชิงฟังก์ชันใน Ruby หรือไม่
ให้ฉันตอบคำถามเหล่านี้ให้คุณเพื่อให้คุณได้รับแนวคิดที่ดีขึ้นเกี่ยวกับวิธีการทำงาน
ฟังก์ชั่นการเขียนโปรแกรมคืออะไร
ไม่ใช่แค่แฟชั่นหรือคำแฟนซี แต่เป็นกระบวนทัศน์การเขียนโปรแกรมจริงที่มีมาช้านานแล้ว แต่เพิ่งกลับมาได้รับความนิยม
และแนวคิดพื้นฐานเบื้องหลังกระบวนทัศน์นี้เข้าใจง่ายกว่าที่คุณคิด
ในการเขียนโปรแกรมเชิงฟังก์ชัน เรา หลีกเลี่ยงการเปลี่ยนสถานะ และเราพยายามเขียน ฟังก์ชันที่ "บริสุทธิ์" .
การหลีกเลี่ยงการเปลี่ยนแปลงสถานะหมายความว่าฟังก์ชันเหล่านี้จะไม่เปลี่ยนแปลงสิ่งใดนอกฟังก์ชัน ไม่มีตัวแปรอินสแตนซ์ ไม่เปลี่ยนแปลงวัตถุที่ส่งผ่านเข้ามา...
ไม่มีเลย!
ในภาษาการเขียนโปรแกรมที่ใช้งานได้ (เช่น Haskell) ข้อมูลทั้งหมดจะไม่เปลี่ยนแปลง
มีบางอย่างเช่นตัวแปร แต่มีพฤติกรรมเหมือนในโลกคณิตศาสตร์ เมื่อกำหนดค่าตัวแปรแล้ว คอมไพเลอร์จะไม่อนุญาตให้คุณกำหนดตัวแปรนี้ใหม่ด้วยค่าอื่น
ประโยชน์ของการเขียนโปรแกรมเชิงฟังก์ชัน
ความไม่เปลี่ยนรูปเป็นข้อได้เปรียบหลักของการเขียนโปรแกรมเชิงฟังก์ชัน เนื่องจากข้อมูลที่เปลี่ยนแปลงได้อาจนำไปสู่ข้อผิดพลาดเล็กๆ น้อยๆ ที่ติดตามได้ยาก
ตัวอย่าง :
def all_different_from_first?(arr) first = arr.shift arr.all? { |n| n != first } end arr = [1,3,5,7,9] p all_different_from_first?(arr) # true
ในตัวอย่างนี้ ฉันต้องการค้นหาว่าองค์ประกอบทั้งหมดในอาร์เรย์แตกต่างจากองค์ประกอบแรกหรือไม่
ในการทำงานนี้ เราจำเป็นต้องลบองค์ประกอบแรกออกจากอาร์เรย์ &ในเวลาเดียวกันให้บันทึกองค์ประกอบนี้ เพื่อที่เราจะสามารถเปรียบเทียบกับส่วนที่เหลือได้
เราจะทำอย่างนั้นได้อย่างไร
เรากำลังทำงานกับอาร์เรย์ &หากคุณดูรายการวิธีการที่มีอยู่ คุณจะพบว่าวิธี Array#shift ทำในสิ่งที่เราต้องการได้อย่างแท้จริง
มันใช้งานได้ดีจนถึง…
…คุณดูค่าของ arr
หลังจากเรียกใช้เมธอดหนึ่งครั้ง:
all_different_from_first?(arr) # true arr # [3,5,7,9]
เซอร์ไพรส์!
อาร์เรย์สูญเสียหนึ่งองค์ประกอบ (1
) และเราไม่ได้สังเกต
บั๊กที่เปลี่ยนแปลงได้แบบนี้จะหลอกล่อได้
เวอร์ชันคงที่ :
def all_different_from_first?(arr) arr[1..-1].all? { |n| n != arr.first } end
การทำงานเทียบกับ OOP
เราทุกคนควรใช้โปรแกรมเชิงฟังก์ชันหรือไม่
อาจดูเหมือนว่าสถานะที่ไม่เปลี่ยนรูปทั้งหมดนี้ทำให้การเขียนโปรแกรมเชิงฟังก์ชันตรงข้ามกับ OOP โดยสิ้นเชิง และในแง่หนึ่งมันก็เป็นเช่นนั้น แต่ก็ยังมีวิธีที่ กระบวนทัศน์การเขียนโปรแกรมทั้งสองสามารถทำงานร่วมกันได้ .
ไม่เลย ไม่จำเป็นต้องเร่งรีบและลงโปรแกรมฟังก์ชันเต็มรูปแบบ Ruby ออกแบบมาสำหรับ OOP ดังนั้นคุณจะต้องต่อสู้กับธัญพืช
ข่าวดี :
คุณยังสามารถใช้แนวคิดที่ดีที่สุดจากการเขียนโปรแกรมเชิงฟังก์ชันและนำไปใช้กับโค้ด Ruby ของคุณได้
มาพูดถึงวิธีการทำกัน
ลดการกลายพันธุ์ให้มากที่สุด
วิธีหนึ่งที่ทำได้คือหยุดใช้ attr_accessor
ติดเฉพาะ attr_reader
.
หลังจากที่คุณทำเช่นนั้น คุณจะต้องคอยจับตาดูสตริง อาร์เรย์ และแฮช
มีวิธีการที่จะเปลี่ยนวัตถุเหล่านี้:
- วิธีการส่วนใหญ่ที่ลงท้ายด้วย
!
(เช่นgsub!
) - ลบ
- อัพเดท
- ชัดเจน
- เปลี่ยน / ไม่เปลี่ยน / ป๊อป / กด
ขั้นตอนแรกคือการตระหนักถึงวิธีการเหล่านี้
ถ้าคุณต้องใช้หนึ่งในวิธีการเหล่านี้ คุณสามารถทำงานกับวัตถุที่ซ้ำกัน
กำหนดสตริงและโคลนของสตริงนั้น :
str = "abcd" dup = str.dup
เราจะได้ผลลัพธ์เหล่านี้เมื่อเราclear
สตริงที่ซ้ำกัน:
dup.clear # str => "abcd" # dup => ""
ซึ่งจะทำให้สตริงเดิมปลอดภัย
การสมัครบางส่วน
การเขียนโปรแกรมเชิงฟังก์ชันมีมากกว่าข้อมูลที่ไม่เปลี่ยนรูปและฟังก์ชันบริสุทธิ์
เช่นเดียวกับการใช้งานฟังก์ชันบางส่วน หรือที่เรียกว่า “currying”
ตัวอย่าง :
def add(a,b) a + b end add_five = method(:add).curry[5] add_five.call(5) # 10 add_five.call(20) # 25
สังเกตว่า add
วิธีรับสองอาร์กิวเมนต์ แต่โดยใช้ curry
วิธีที่เราสามารถ "โหลดล่วงหน้า" หนึ่งในอาร์กิวเมนต์ได้
จากนั้นเราจะได้แลมบ์ดาที่เราเรียกได้โดยใช้อาร์กิวเมนต์ที่ 2
นี่เป็นอีกตัวอย่างหนึ่ง :
list = (1..10) greater_than = ->(x,y) { y > x }.curry list.select(&greater_than.(5)) # [6, 7, 8, 9, 10] list.select(&greater_than.(8)) # [9, 10]
อีกหนึ่งตัวอย่าง :
divisible_by = ->(x,y) { y % x == 0 }.curry list.select(&divisible_by.(5)) # [5, 10] list.select(&divisible_by.(2)) # [2, 4, 6, 8, 10]
สรุป
คุณได้เรียนรู้เกี่ยวกับ Functional Programming ที่สำคัญคือฟังก์ชันล้วนๆ และข้อมูลที่ไม่เปลี่ยนรูป เป็นเพียงวิธีคิดเกี่ยวกับโค้ดของคุณและไม่เข้ากันกับ OOP โดยสิ้นเชิง
ขอบคุณที่เข้ามาอ่าน อย่าลืมสมัครรับจดหมายข่าวหากยังไม่ได้สมัคร! 🙂