function countdown(num) {
	console.log(num)
	if (num <= 1) { // base case
		return;
	} else { // recursive case
		countdown(num - 1);
	}
}
countdown(3) // 3, 2, 1
function greet(name) {
	console.log("hello, " + name);
	greet2(name);
	console.log("getting ready to say bye");
	bye();
}
function greet2(name) {
	console.log("how are you " + name);
}
function bye() {
	console.log("bye");
}
greet("maggie");
First, the computer allocates memory for greet function. Then it prints “hello maggie”

greet2 function. Then it prints "how are you maggie"
    greet function is partially completed. When you call a function from another function, the calling function is paused in a partially completed state.
greet2 function, you’re back to the greet function, and you pick off where you left off. It prints "getting ready to say bye" then calls bye function.# iterative
def look_for_key(main_box):
	pile = main_box.make_a_pile_to_look_through()
	while pile is not empty:
		box = pile.grab_a_box()
		for item in box:
			if item.is_a_box():
				pile.append(item)
			elif item.is_a_key():
				print "found the key!"
# recursive
def look_for_key(box):
	for item in box:
		if item.is_a_box():
			look_for_key(item)
		elif item.is_a_key():
			print "found the key!"
tail recursion.tail recursion (https://stackoverflow.com/questions/33923/what-is-tail-recursion)
      var reverseList = function(head) {
       if(head === null) {
          return head;
      }
     
      let newHead = head;
      if(head.next !== null) {
          newHead = reverseList(head.next);  
          head.next.next = head;
      } 
        
      // the final one has to point to null
      // the middle nodes , doesn't matter
      head.next = null
        
      return newHead;
  }
  var mergeTwoLists = function(list1, list2) {
      if(!list1){
          return list2;
      }
        
      if(!list2) {
          return list1;
      }
    
      if(list1.val <= list2.val) {
         list1.next = mergeTwoLists(list1.next, list2);
         return list1; 
      } else {
          list2.next = mergeTwoLists(list1, list2.next);
          return list2
      }        
    
  }