Functional Programming
    // functions
    let func_add = (a,b) => {
        return a = b;
    };
    let result_add = func_add(12,35);
    console.log(result_add);
Types of functions
First class functions:: These are the functions that can be assigned to a variable, passed into another function, or returned from another function just like any other normal value.
    // first class functions
    let firstclass_func = (a,b,str) => {
        return str=="add"?a+b:(str=="multiply"?a*b:(str=="divide"?a/b:(str=="subtract"?a-b:str)));
    };
    let result1_add = firstclass_func(12.49,23.34,"add");
    console.log(result1_add); // 35.83
    let result1_multiply = firstclass_func(12.49,23.34,"multiply");
    console.log(result1_multiply); // 291.5166
    let result1_divide = firstclass_func(12.49,23.34,"divide");
    console.log(result1_divide); // 0.5351328191945158
    let result1_subtract = firstclass_func(12.49,23.34,"subtract");
    console.log(result1_subtract); // -10.85
    let result_invalid_arguments = firstclass_func(12.49,23.34,"don't calculate anything");
    console.log(result_invalid_arguments); // don't calculate anything
Higher Order functions These are the functions that take a function as an argument, or return a function as a return value.
    // higer order function
    // take function as argument
    let higher_order_function1 = (func1) => {
        let add = 23 + func1();
        console.log(`addition of 23 and ${func1()} gives ${add}`);
    };
    let firstclass_func1 = () => {
        return 33.33;
    };
    higher_order_function1(firstclass_func1); // addition of 23 and 33.33 gives 56.33

    // return function as value
    let higher_order_function2 = () => {
        return () => { console.log("a2rp: an Ashish Ranjan presentation"); };
    };
    higher_order_function2()(); // a2rp: an Ashish Ranjan presentation
Lambda functions These are the functions whish are passed in to or returned from another function.
    // higer order function
    // take function as argument
    let higher_order_function1 = (func1) => {
        let add = 23 + func1();
        console.log(`addition of 23 and ${func1()} gives ${add}`);
    };
    let firstclass_func1 = () => {
        return 33.33;
    };
    higher_order_function1(firstclass_func1); // addition of 23 and 33.33 gives 56.33

    // return function as value
    let higher_order_function2 = () => {
        return () => { console.log("a2rp: an Ashish Ranjan presentation"); };
    };
    higher_order_function2()(); // a2rp: an Ashish Ranjan presentation
Imperative Programming versus Declarative Programming
Programming Paradigms
Imperative programming:: Imperative code focuses on writing an explicit sequence of commands to describe how we want the computer to do things.
Functional [Haskel]
Login [Prolog]
Declarative programming:: Declarative code focuses on specifying the result of what we want.
Procedual [C programming language]
Object Oriented [C++, Java]
    const numbers = [10,20,30,40,50,60,70];
    
    // imperative programming
    let imperative_input_array = [];
    for (let i=0; i<numbers.length; ++i) {
        imperative_input_array.push(numbers[i]);
    }
    console.log(`values in imperative_input_array are ${imperative_input_array}`); // values in imperative_input_array are 10,20,30,40,50,60,70

    //  declarative programming
    let declarative_input_array = numbers.map(number => number);
    console.log(`values in declarative_input_array are ${declarative_input_array}`); // values in declarative_input_array are 10,20,30,40,50,60,70
Pass Arguments to Avoid External Dependence in a Function
    let number_1 = 23;
    let incrementer = (value) => {
        return (value+1);
    };
    console.log(`${number_1} on incrementing becomes ${incrementer(number_1)}`); // 23 on incrementing becomes 24
Refactor global variables out of functions
    console.log("\n\n");
    console.log("refactor global variables outside functions");
    const global_array = [3, "a2rp", true];
    const original_values = global_array;
    let add_element_to_array = (the_array) => {
        the_array.push(12345);
        return the_array;
    };
    let new_array = add_element_to_array(global_array);
    console.log(`original values = ${original_values}`); // original values = 3,a2rp,true,12345
    console.log(`global array:: ${global_array} after add new array:: ${new_array}`); // global array:: 3,a2rp,true,12345 after add new array:: 3,a2rp,true,12345

    let remove_element_from_array = (the_array) => {
        the_array.splice(the_array.length-1,1);
        return the_array;
    };
    let renew_array = remove_element_from_array(global_array);
    console.log(`original values = ${original_values}`); // original values = 3,a2rp,true
    console.log(`global array:: ${global_array} after remove new array:: ${renew_array}`); // global array:: 3,a2rp,true after remove new array:: 3,a2rp,true

    console.log(`is orignial array: "${original_values}" = new array: ${renew_array} ??? ${original_values==renew_array}`);
    // is orignial array: "3,a2rp,true" = new array: 3,a2rp,true ??? true
use map method to extract data from array
The map method iterates over each item in an array and returns a new array containing the results of calling the callback function on each element. It does this without mutating the original array.
    console.log("map method");
    let original_array = [
        {id: 1, name: "Ashish"},
        {id: 2, name: "Ranjan"},
        {id:3, name: "Kumar"}
    ];
    let all_names = original_array.map(value=>value.name);
    console.log(`all names in the array ${JSON.stringify(original_array)} are:: ${all_names}`);
    // all names in the array [{"id":1,"name":"Ashish"},{"id":2,"name":"Ranjan"},{"id":3,"name":"Kumar"}] are:: Ashish,Ranjan,Kumar
implement map on prototype
map is a pure function and its output depends solely on its input