Skip to content

Instantly share code, notes, and snippets.

@Ghanshyam-K-Dobariya
Last active July 16, 2021 08:58
Show Gist options
  • Save Ghanshyam-K-Dobariya/e98e328088cddc856c1b1b6c122a5c0d to your computer and use it in GitHub Desktop.
Save Ghanshyam-K-Dobariya/e98e328088cddc856c1b1b6c122a5c0d to your computer and use it in GitHub Desktop.

Create a Wallet function that can be called multiple times & maintain balance and transactions, we should be able to call it in a chain way. example is 👇

Wallet(); // prints nothing or its up to you whatever you want to print.
Wallet().getBalance(); // Balance is 0.

Wallet().add(50).add(70).getBalance(); // Added 50. Added 70. Balance is 120.
Wallet().showTransactions(); // +50 <<Date time>>. +70 <<Date time>>.

Wallet().spend(20).getBalance().spend(40).getBalance() // Spent 20. Balance is 100. Spent 40. Balance is 60.
Wallet().showTransactions(); // +50 <<Date time>>. +70 <<Date time>>. -20 <<Date time >>. -40 <<Date time >>.


Wallet().spend(20000); // Error Insufficient Balance.
Wallet().add(-100); // Error negative balance can't be added...

Observations

Here we need to maintain balance and transactions throughout all the calls of Wallet(), when this function is called multiple times (ie on new lines as well), that time also we must have original refernce of balance and transactions array.

By original reference I mean, reference which was created 1st time.

1 solution is we keep these 2 variables in global context. then solution looks like this.

Solution 1 - Use global variables

var balance = 0;
var transactions = [];

function Wallet() {
const obj = {
 add, spend, getBalance, showTransactions,
};

function add(value) {
 /* throw error if value is <= 0 */
 transactions.push(`+${value} - ${new Date()}`);
 balance += value;
 console.log(`Added ${value}`);
 return obj;
}


function spend(value) {
 /* throw error if value > balance */
 transactions.push(`-${value} - ${new Date()}`);
 balance -= value;
 console.log(`Spent ${value}`);
 return obj;
}


function getBalance() {
 console.log(`Balance is ${balance}`);
 return obj;
}

function showTransactions() {
 console.log(transactions.join('\n'));
 return obj;
}
return obj;
};

Limitations of solutions 1 We can't export this function as module as balance and transactions are global.

We can use concept of function returns function in 1 more possible way. Lets assume Wallet is returned from parent function and that parent function takes care of all the balance and transactions variables, now we can export the Wallet function without any concern.

Solution 2

function getWallet() {
    var balance = 0;
    var transactions = [];
    const obj = {
        add,
        spend,
        getBalance,
        showTransactions,
    };

    function add(value) {
        /* throw error if value is <= 0 */
        transactions.push(`+${value} : ${new Date()}`);
        balance += value;
        console.log(`Added ${value}`);
        return obj;
    }

    function spend(value) {
        /* throw error if value > balance */
        transactions.push(`-${value} : ${new Date()}`);
        balance -= value;
        console.log(`Spent ${value}`);
        return obj;
    }

    function getBalance() {
        console.log(`Balance is ${balance}`);
        return obj;
    }

    function showTransactions() {
        console.log(transactions.join('\n'));
        return obj;
    }

    function W() {
        return obj;
    }
    return W;
};


Wallet = getWallet();
/* export Wallet, not getW*/

Concepts you need to know are

  1. function currying
  2. function hoisting
  3. closures

There can be multiple ways to solve this problem as no one is perfect and there is nothing like perfect solution.

Happy Coding. 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment