Reputation: 1018
In Javascript, I'm using console.log for debugging. It would seem that once I have the logic worked out, I could confidently take out the debugging statements without affecting logic. Here's evidence to the contrary. (Said tentatively, because I'm probably wrong on that count!) First, the program; please look for the long series of asterisks. (I'm going through a text book on my own; this is an assignment there, but you're not helping me with homework. I'm trying to understand the language!)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Why is call to console.log needed?</title>
<script type="text/javascript">
/** IterAbstract: Constructor for a means of visiting every object in
* a collection.
*
* @param arr: the collection, either an ArraySeq or a RangeSeq
* @returns
* method getNext returns (1) (most likely) a member of arr;
* possibly the value undefined, if that's in the collection, or
* (2) the value undefined, an tentative indication that there
* are no further elements.
* method getAtEnd returns (1) true, if no further elements remain,
* or (2) false, if further elements remain to be sent.
* @constructor IterAbstract
* Users should use only the two methods.
*/
function IterAbstract (arr) {
this.arr = arr;
this.last = this.arr.length - 1;
this.lastSent = null;
this.atEnd = false;
}
/* *************************
The focus is the call to console.log at the start of the
function following these comments.
************************* */
/* The expected behavior of this file is that when function
logFive receives a two-element array, there will be three calls
to getNext. The first call uses the return commented "return
for the first element"; it returns the first element of the
array and logFive puts it on console.log. The second call uses
the return commented "return for all other elements"; that
return makes all other elements available for logFive to record
on console.log. The third call creates the unambiguous "we're
past the end of file" signal (a combination of this.atEnd=true
and returning the undefined value); it uses the return
commented "after-the-end return".
When logFive gets an array [1, 2], we expect to see two calls
to console.log, one with each element.
When logFive gets an array [null, undefined], we expect the same,
though with different (and admittedly squirrely) elements
demonstrated.
Good: When the subject call to console.log occurs (not commented
out), the expected behavior occurs. Though there are interspersed
lines starting "getNext", we see rows with the four expected
outputs: 1, 2, null, and undefined.
Bad: When we comment out the subject call to console.log, we see
three of the four expected rows: 1, 2, and null.
There is a series of three other calls to console.log designed
to show us which exit the code uses. They have been commented out
before; let's uncomment the them.
Good: Though there are interspersed lines starting "getNext", we
see the four expected rows. The code is using the expected
returns.
Why do these debugging calls to console.log affect actual logic
flow? (he he) Where's the user error here?
*/
IterAbstract.prototype.getNext = function () {
console.log("getNext this.lastSent=" + this.lastSent +
" this.atEnd=" + this.atEnd);
if (this.lastSent === this.last) {
//console.log("getNext after-the-end return this.lastSent="+
// this.lastSent+" this.last="+this.last);
this.atEnd = true;
return undefined; // after-the-end return
}
if (this.lastSent === null) {
this.lastSent = 0;
//console.log("getNext first exit element=0");
return this.arr[0]; // return for the first element
}
var sent=this.lastSent+1;
//console.log("getNext normal exit element="+sent);
return this.arr[++this.lastSent]; // return for all other elements
};
IterAbstract.prototype.getAtEnd = function () { return this.atEnd; };
/** logFive: Shows the first five elements of a collection on
* console.log; less, if the collection has less.
* @param arr: the collection, either an ArraySeq or a RangeSeq
*/
function logFive (arr) {
var iterArr = new IterAbstract(arr);
/*console.log("after Constructor iterArr.arr="+iterArr.arr+
" iterArr.last="+iterArr.last+
" iterArr.lastSent="+iterArr.lastSent+
" iterArr.atEnd="+iterArr.atEnd); */
var response;
for (i=0; i < 5; i++) {
//console.log("start iter i="+i+
// " iterArr.atEnd="+iterArr.atEnd);
response = iterArr.getNext();
/*console.log("iter i="+i+" response="+response+
" iterArr.atEnd="+iterArr.atEnd);*/
if (response === undefined && iterArr.getAtEnd()) return;
//console.log("iter normal exit");
console.log(response);
} }
function ArraySeq ( arr ) {
return arr;
}
console.log ("logFive(new ArraySeq([1, 2]));");
logFive(new ArraySeq([1, 2]));
// → 1
// → 2
console.log ("logFive(new ArraySeq([null,undefined]);");
logFive(new ArraySeq([null,undefined]));
// → null
// → undefined
</script>
</head>
<body>
<p>Output for this program goes to console.log.</p>
<p>In Firefox, press Ctrl-Shift-K to see that output.</p>
<p>In Chrome, press Ctrl-Shift-J to see that output.</p>
</body>
</html>
The output of that code is:
logFive(new ArraySeq([1, 2]));
getNext this.lastSent=null this.atEnd=false
1
getNext this.lastSent=0 this.atEnd=false
2
getNext this.lastSent=1 this.atEnd=false
logFive(new ArraySeq([null,undefined]);
getNext this.lastSent=null this.atEnd=false
null
getNext this.lastSent=0 this.atEnd=false
undefined
getNext this.lastSent=1 this.atEnd=false
Sweet! Almost done. That's just what I want, except for the lines starting "getNext". Let's comment out that call to console.log at the beginning of getNext. Then, the output becomes:
logFive(new ArraySeq([1, 2]));
1
2
logFive(new ArraySeq([null,undefined]);
null
Hey! No fair. I need that other line, "undefined". Where'd it go?
Maybe if I can figure out what return statement was used each time, I'll learn something interesting. I'll uncomment the three calls to console.log at each exit point in getNext. Now, the output becomes:
logFive(new ArraySeq([1, 2]));
getNext first exit element=0
1
getNext normal exit element=1
2
getNext after-the-end return this.lastSent=1 this.last=1
logFive(new ArraySeq([null,undefined]);
getNext first exit element=0
null
getNext normal exit element=1
undefined
getNext after-the-end return this.lastSent=1 this.last=1
Sigh. If I can put debugging statements in, I can get the right output, except for the extra junk.
Wassup? Thanks in advance!
Upvotes: 2
Views: 404
Reputation: 925
Firefox groups both null and undefined together. Putting another console.log in between them force them to no longer by grouped. Grouping is there to help keep the console cleaner when multiple similar logs are displayed, like in a loop for example.
Here Firefox logs everything on a separate line because no line back to back are similar :
But for some reason it considers null and undefined similar enough to be grouped together when they are back to back :
Your output is correct. The way Firefox displays it is not.
Upvotes: 2