4

First of all, I apologize if this is a stupid question. It is very possible that I'm completely missing something trivial. I don't know what it is. So here's the problem:

(context: I'm making arbitrary precision math library in JavaScript)

Here's the code:

    function processInput(n){       
        let parts;
        let numer, denom, positivity;
        if(is.negative(n)){
            positivity = -1;
            n = n.substr(1);
        } else {
            positivity = 1;
        }
        ////////// RELEVANT SECTION STARTS ///////////////
        console.log(n); // prints "1 2/3", which is what I'm testing
        if(is.zero(n)){
            numer = [0], denom = [1], positivity = 0;
        } else if(is.mixedFrac(n)){
            console.log(n); // <------ error: "n is not defined". How???
            parts = n.match(/\d+/g).map(function(e){
                return ArrayOps.wholeToArnum(n);
            });
        ////////// RELEVANT SECTION ENDS ///////////////
            let w = parts[0], 
                n = parts[1],
                d = parts[2];
            let n1 = ArrayOps.multiply(w, d);
            numer = ArrayOps.add(n1, n);
            denom = d;
        } else if(is.frac(n)){
            parts = n.match(/\d+/g).map(function(e){
                return ArrayOps.wholeToArnum(e);    
            });
            numer = parts[0];
            denom = parts[1];
        } else if(is.repeatingDecimal(n)){
            let temp = n.split('...');
            let dec = ArrayOps.decToArnum(temp[0]);

            let decLength = dec.decLength;
            let repDec = ArrayOps.repDecToArnum(temp[1], decLength);

            let n1 = dec.numer;
            let d1 = dec.denom;
            let n2 = repDec.numer;
            let d2 = repDec.denom;
            n1 = ArrayOps.multiply(n1, d2);
            n2 = ArrayOps.multiply(n2, d1);
            numer = ArrayOps.add(n1, n2);
            denom = ArrayOps.multiply(d1, d2);
        } else if(is.decimal(n)){
            n = ArrayOps.decToArnum(n);
            numer = n.numer;
            denom = n.denom;
        } else if(is.wholeNum(n)){
            numer = ArrayOps.wholeToArnum(n);
            denom = [1];
        } else {
            throw new Error(`${n} is not a valid form of input.`);
        }
        return {numer, denom, positivity};
    }

(JS Fiddle: http://jsfiddle.net/k4mjwg57/3/)

Basically, this is what it comes down to:

function process(n){
  if(passTest(n)){
    console.log(n); // Error: "n is not defined"
  }
}

Here's the screenshot from debugging: n is defined.

As I have highlighted in red rectangle, the debugger clearly shows n = "1 2/3", and it passes the test (is.mixedFrac(n)), because it is mixed fraction.

There's nothing in is.mixedFrac(n) that can change n.

Continuing produces the following error: The error

If n wasn't defined in the first place, I shouldn't have passed the test. Can someone help me with what's going on? Again, I'm sure it's a trivial mistake. But I'm not seeing it.

Things to note:

  • Changing the if control to if(is.mixedFrac(n) && n) still passes to inside the bracket
  • I know screenshot is discouraged, but if you look at it, and I hover my mouse on n while on break point, it will still show that n is "1 2/3".
  • There is absolutely no async stuff going on. There's no timeout, ajax, promise, or anything going on. The entirety of my code is quite rudimentary.
  • In FireFox, it gives me the following error: "ReferenceError: can't access lexical declaration `n' before initialization"
J.Ko
  • 964
  • 12
  • 26

1 Answers1

3

You redeclared the variable n inside the same if statement (which is a block). let is block scoped, which means that n exists only within that block. But you've declared a variable with the same name as the scope above it, which overwrites it.

    ////////// RELEVANT SECTION STARTS ///////////////
    console.log(n); // prints "1 2/3", which is what I'm testing
    if(is.zero(n)){
        numer = [0], denom = [1], positivity = 0;
    } else if(is.mixedFrac(n)){
        console.log(n); // <------ error: "n is not defined". How???
        parts = n.match(/\d+/g).map(function(e){
            return ArrayOps.wholeToArnum(n);
        });
    ////////// RELEVANT SECTION ENDS ///////////////
        let w = parts[0], 
            n = parts[1], // HERE!
            d = parts[2];
        let n1 = ArrayOps.multiply(w, d)

let n = [1,2,3]
if (true) {
 console.log(n)
 let n = 10
}

This is what you have essentially done. The let n declaration is now the only n that can exist in that block, and you've tried to console.log the variable before it has been declared.

Andrew
  • 7,201
  • 5
  • 25
  • 34