ทำไมต้องเป็น Functional Programming?

ทำไมต้องเป็น Functional Programming?

เริ่มต้นด้วยการยกตัวอย่าง:

const printOddNumbers = (ar) => {
    let odd = [];
    for(let i=0;i<ar.length;i++) {
        if(ar[i]%2==1) {
            odd.push(ar[i]);
        }
    }
    for(let i=0;i<odd.length;i++) {
        console.log(odd[i]);
    }
}
printOddNumbers([1,2,3,4,5,6]);
const logger = e => console.log(e);
const printOddNumbers = (ar) => {
    ar.filter(x => x%2)
      .forEach(logger);
};
printOddNumbers([1,2,3,4,5]);

เรามี 2 โปรแกรมสำหรับพิมพ์เลขคี่ไปที่คอนโซล ความแตกต่างระหว่างกระบวนทัศน์การเขียนโปรแกรมเหล่านี้คือลักษณะที่เราอ่านและเขียนโค้ด

Imperative :

Imperative code หมายถึงโค้ดที่เน้นไปที่HOWเป็นหลักในการทำบางสิ่งในแง่ของคำสั่ง/ขั้นตอน เนื่องจากลักษณะHOWของสไตล์นี้ สมองของเราต้องรันโค้ดทางจิตใจก่อนที่เราจะเข้าใจจุดประสงค์ของมัน เราไม่สามารถเหลือบมองโค้ดและเข้าใจได้ทันทีว่าโค้ดนั้นกำลังทำอะไรอยู่

Declarative :

  • ในรูปแบบของ declarative How จะไม่สำคัญ สิ่งที่สำคัญคือWhat ในรูปแบบนี้ระบุโปรแกรมWhatที่ต้องทำในแง่ของการแสดงออก Functional Programming นั้นโดยธรรมชาติแล้วจะมีความชัดเจนมากกว่า

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

Functional Programming คืออะไร?

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

ฟังก์ชั่นบริสุทธิ์คืออะไร?

ในจิตวิญญาณของการเขียนโปรแกรมเชิงฟังก์ชัน คำจำกัดความที่เหมาะสมของฟังก์ชันบริสุทธิ์คือ

  • ฟังก์ชันไม่เพียงรับอินพุตบางส่วนเท่านั้น แต่ยังต้องส่งคืนเอาต์พุตบางส่วนด้วย ตัวอย่างด้านล่างไม่เข้าเกณฑ์สำหรับฟังก์ชันเนื่องจากไม่ส่งคืนผลลัพธ์ใดๆ แทน ทำให้เกิดผลข้างเคียงโดยการพิมพ์ไปยังคอนโซล
const areaOfCircle = (radius) => {
    console.log(3.14 * radius * radius);
};
areaOfCircle(2);
  • ฟังก์ชั่นจะดีกว่าถ้าชื่อฟังก์ชันสามารถอธิบายความสัมพันธ์ทางความหมาย b/w อินพุตและเอาต์พุต
f(r) = π * r * rในตัวอย่างข้างต้น areaOfCircle อธิบายความสัมพันธ์เชิงความหมาย b/w ฟังก์ชันอินพุตและเอาต์พุตได้อย่างสมบูรณ์แบบ
  • ในฟังก์ชัน อินพุตและเอาต์พุตควรเป็นแบบตรง การเรียกใช้ฟังก์ชันควรทำธุรกิจแยกจากส่วนที่เหลือของโปรแกรม มันไม่ควรทำให้เกิดใด ๆ ที่มีผลข้างเคียง ในตัวอย่างด้านล่าง ทั้งอินพุตและเอาต์พุตเป็นทางอ้อมและได้รับการเปลี่ยนแปลงตลอดการดำเนินการของโปรแกรม
let pi = 3.14;
let radius, area;
const areaOfCircle = () => {
    radius = pi * radius * radius;
    return radius;
};
radius = 2;
area = areaOfCircle(pi, radius)
console.log(area);
radius = 3;
area = areaOfCircle(pi, radius)
console.log(area);
  • ฟังก์ชันสามารถมีอินพุตทางอ้อมได้ตราบเท่าที่ไม่มีการกลายพันธุ์หรือเปลี่ยนแปลง อินพุตทางอ้อมควรคงที่ตลอดหลักสูตร ที่นี่ pi ไม่เคยเปลี่ยนแปลง ดังนั้นตัวแปร pi เนื่องจากอินพุตทางอ้อมจึงถูกต้อง
const pi = 3.14;  
const areaOfCircle = (radius) => {
    // pi is in-direct input here, 
    // it is as equivalent as replacing the value of pi
    // inline i.e 3.14 * radius * radius
    return pi * radius * radius; 
};
let area1 = areaOfCircle(2);
console.log(area1);
let area2 = areaOfCircle(3);
console.log(area2);
  • การเรียกใช้ฟังก์ชันควรส่งคืนเอาต์พุตเดียวกันผ่านอินพุตเดียวกันกี่ครั้งก็ตามเมื่อมีการเรียก
 
function counter() {
    let c = 0;
    // we are closing over the value c, 
    // forming a closure and mutating it on every function execution 
    // resulting in different output.
    return function() {
        return ++c; 
    }
}
const myCounter = counter();
// these are not pure function call, as we are not getting 
// the same output every time, given the same input which in this
// case is no input.
myCounter() // 1
myCounter() // 2
myCounter() // 3
// Same with random number generator
function random() {
    return Math.random();
}
// no input, is the valid input
random(); 
random();
random();

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

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

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

const pi = 3.14;
function areaOfCircle(radius) {
    return pi * radius * radius;
}
function areaOfCylinder(radius, height) {
    return areaOfCircle(radius) * height;
    // return areaOfCircle(2) * height is
    // equivalent to 
    // return 12.56 * height;
    // We just replace it's result as we are guranteed by the 
    // fact that areaOfCircle is a pure function and always 
    // result in same output on input 
}
let cylinderArea = areaOfCylinder(2,3);
console.log(cylinderArea);

คุณอาจจะคิดนี้อาจทำให้ CPU และค่าหน่วยความจำที่เราจะได้รับการคัดลอกข้อมูลเดียวกันซ้ำแล้วซ้ำอีกครั้งนั่นคือสิ่งที่เราได้รับความช่วยเหลือจากห้องสมุดไม่เปลี่ยนรูปโครงสร้างข้อมูลเช่นImmutable.js และ Google ฝรั่ง พวกเขาสรุปสิ่งเหล่านี้ออกจากบริบทตรรกะทางธุรกิจของเราและดูแลเรื่องนี้อย่างมีประสิทธิภาพมากขึ้น ข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่พวกเขาทำในบล็อกอื่น

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

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

Credit : Medium.com

Leave a Comment

Your email address will not be published.