In Progress
Unit 1, Lesson 21
In Progress

Removing Debug Output

Video transcript & code

I've got some old code lying around which implements Conway's game of life, and I thought it would be fun to fire it up again. Here's some code to generate and print three generations of the classic "glider" shape. Let's see what it prints.

require './mildly-functional-gol'

glider = <<END
.o......
..o.....
ooo.....
........
........
........
........
........
END

board = BoardGeneration.new(glider)
puts board = board.next_generation
puts
puts board = board.next_generation
puts
puts board = board.next_generation

# >> [., o, ., ., ., ., ., .]
# >> [., ., o, ., ., ., ., .]
# >> [o, o, o, ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/0 are [., ., ., ., o, ., ., .]
# >> *** Neighbors of 1/0 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 2/0 are [., ., ., o, ., ., o, .]
# >> *** Neighbors of 3/0 are [., ., ., ., ., o, ., .]
# >> *** Neighbors of 4/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/1 are [., ., o, ., ., ., o, o]
# >> *** Neighbors of 1/1 are [., o, ., ., o, o, o, o]
# >> *** Neighbors of 2/1 are [o, ., ., ., ., o, o, .]
# >> *** Neighbors of 3/1 are [., ., ., o, ., o, ., .]
# >> *** Neighbors of 4/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/2 are [., ., ., ., o, ., ., .]
# >> *** Neighbors of 1/2 are [., ., o, o, o, ., ., .]
# >> *** Neighbors of 2/2 are [., o, ., o, ., ., ., .]
# >> *** Neighbors of 3/2 are [o, ., ., o, ., ., ., .]
# >> *** Neighbors of 4/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/3 are [., o, o, ., ., ., ., .]
# >> *** Neighbors of 1/3 are [o, o, o, ., ., ., ., .]
# >> *** Neighbors of 2/3 are [o, o, ., ., ., ., ., .]
# >> *** Neighbors of 3/3 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 4/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/7 are [., ., ., ., ., ., ., .]
# >> ........
# >> o.o.....
# >> .oo.....
# >> .o......
# >> ........
# >> ........
# >> ........
# >> ........
# >> 
# >> *** Neighbors of 0/0 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 1/0 are [., ., ., ., ., o, ., o]
# >> *** Neighbors of 2/0 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 3/0 are [., ., ., ., ., o, ., .]
# >> *** Neighbors of 4/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/1 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 1/1 are [., ., ., o, o, ., o, o]
# >> *** Neighbors of 2/1 are [., ., ., ., ., o, o, .]
# >> *** Neighbors of 3/1 are [., ., ., o, ., o, ., .]
# >> *** Neighbors of 4/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/2 are [., o, ., ., o, ., ., o]
# >> *** Neighbors of 1/2 are [o, ., o, ., o, ., o, .]
# >> *** Neighbors of 2/2 are [., o, ., o, ., o, ., .]
# >> *** Neighbors of 3/2 are [o, ., ., o, ., ., ., .]
# >> *** Neighbors of 4/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/3 are [., ., o, ., o, ., ., .]
# >> *** Neighbors of 1/3 are [., o, o, ., ., ., ., .]
# >> *** Neighbors of 2/3 are [o, o, ., o, ., ., ., .]
# >> *** Neighbors of 3/3 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 4/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/4 are [., ., o, ., ., ., ., .]
# >> *** Neighbors of 1/4 are [., o, ., ., ., ., ., .]
# >> *** Neighbors of 2/4 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 3/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/7 are [., ., ., ., ., ., ., .]
# >> ........
# >> ..o.....
# >> o.o.....
# >> .oo.....
# >> ........
# >> ........
# >> ........
# >> ........
# >> 
# >> *** Neighbors of 0/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/0 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 2/0 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 3/0 are [., ., ., ., ., o, ., .]
# >> *** Neighbors of 4/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/1 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 1/1 are [., ., ., ., o, o, ., o]
# >> *** Neighbors of 2/1 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 3/1 are [., ., ., o, ., o, ., .]
# >> *** Neighbors of 4/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/2 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 1/2 are [., ., o, o, o, ., o, o]
# >> *** Neighbors of 2/2 are [., o, ., ., ., o, o, .]
# >> *** Neighbors of 3/2 are [o, ., ., o, ., o, ., .]
# >> *** Neighbors of 4/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/3 are [., o, ., ., o, ., ., .]
# >> *** Neighbors of 1/3 are [o, ., o, ., o, ., ., .]
# >> *** Neighbors of 2/3 are [., o, ., o, ., ., ., .]
# >> *** Neighbors of 3/3 are [o, ., ., o, ., ., ., .]
# >> *** Neighbors of 4/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/4 are [., ., o, ., ., ., ., .]
# >> *** Neighbors of 1/4 are [., o, o, ., ., ., ., .]
# >> *** Neighbors of 2/4 are [o, o, ., ., ., ., ., .]
# >> *** Neighbors of 3/4 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 4/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/7 are [., ., ., ., ., ., ., .]
# >> ........
# >> .o......
# >> ..oo....
# >> .oo.....
# >> ........
# >> ........
# >> ........
# >> ........

YUCK! What's all this garbage in the output?! Oh, I see. I must have left some debugging output in the code when I last worked on it. Well that was inconsiderate of me.

Debug output is a little annoyance that becomes a big problem if left unchecked. It's a "broken window", in the language of the book The Pragmatic Programmer. One programmer leaves a little debug output in the code. Then another programmer leaves some more debug output, and they don't immediately realize it because it's mixed in with the original debug output. Soon the program emits a mass of garbage every time it runs, and legitimate warning or error messages get lost in the mix.

When the problem is confined to a few small files it might be sufficient, if a little tedious, to clean it up by simply visually inspecting the code and removing the offending lines. But in a larger codebase it's all too easy to let the problem go for months and months because it simply feels like too much work to track down all the stray debug lines.

I've got good news for you: all the angst is unwarranted. Today I'm going to show you a Ruby magic trick that will let you track down all those irritating debug statements in a jiffy.

I'm going to work under the assumption that at least some of this debug output was produced with the p method, which we learned about in episode 113. To find out where p is being called, I'm going to redefine the Kernel#p method to simply raise an exception. I specifically raise the base Exception class, since it is less likely to be rescued and thrown away somewhere along the line.

Redefining existing methods like this is often referred to as "monkey-patching". I don't often break out the monkey-patching hammer, but this is one of the rare occasions when I'm glad it's possible in Ruby.

Now I'll run the code again.

require './mildly-functional-gol'

glider = <<END
.o......
..o.....
ooo.....
........
........
........
........
........
END

module Kernel
  def p(*) # !> method redefined; discarding old p
    raise Exception, "debug output!"
  end
end

board = BoardGeneration.new(glider)
puts board = board.next_generation
puts
puts board = board.next_generation
puts
puts board = board.next_generation

# ~> -:16:in `p': debug output! (Exception)
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:58:in `block in grid_from_lines'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:57:in `map'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:57:in `grid_from_lines'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:19:in `initialize'
# ~>    from -:20:in `new'
# ~>    from -:20:in `<main>'

Bang! Just like that, I've got a backtrace that points straight to the errant debugging output. I can follow the trace and remove the offending p call.

When I run the code again, I don't get an exception, but I still get some garbage in the output. Looks like I'm not quite done eliminating debug output yet. Maybe there is a debug puts somewhere in the code.

If so, it poses a slightly trickier problem, since I'm also using puts intentionally. How can I catch the debug puts statements without interfering with the puts statements I wrote on purpose?

require './mildly-functional-gol'

glider = <<END
.o......
..o.....
ooo.....
........
........
........
........
........
END

module Kernel
  def p(*) # !> method redefined; discarding old p
    raise Exception, "debug output!"
  end
end

board = BoardGeneration.new(glider)
puts board = board.next_generation
puts
puts board = board.next_generation
puts
puts board = board.next_generation

# >> *** Neighbors of 0/0 are [., ., ., ., o, ., ., .]
# >> *** Neighbors of 1/0 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 2/0 are [., ., ., o, ., ., o, .]
# >> *** Neighbors of 3/0 are [., ., ., ., ., o, ., .]
# >> *** Neighbors of 4/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/1 are [., ., o, ., ., ., o, o]
# >> *** Neighbors of 1/1 are [., o, ., ., o, o, o, o]
# >> *** Neighbors of 2/1 are [o, ., ., ., ., o, o, .]
# >> *** Neighbors of 3/1 are [., ., ., o, ., o, ., .]
# >> *** Neighbors of 4/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/2 are [., ., ., ., o, ., ., .]
# >> *** Neighbors of 1/2 are [., ., o, o, o, ., ., .]
# >> *** Neighbors of 2/2 are [., o, ., o, ., ., ., .]
# >> *** Neighbors of 3/2 are [o, ., ., o, ., ., ., .]
# >> *** Neighbors of 4/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/3 are [., o, o, ., ., ., ., .]
# >> *** Neighbors of 1/3 are [o, o, o, ., ., ., ., .]
# >> *** Neighbors of 2/3 are [o, o, ., ., ., ., ., .]
# >> *** Neighbors of 3/3 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 4/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/7 are [., ., ., ., ., ., ., .]
# >> ........
# >> o.o.....
# >> .oo.....
# >> .o......
# >> ........
# >> ........
# >> ........
# >> ........
# >> 
# >> *** Neighbors of 0/0 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 1/0 are [., ., ., ., ., o, ., o]
# >> *** Neighbors of 2/0 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 3/0 are [., ., ., ., ., o, ., .]
# >> *** Neighbors of 4/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/1 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 1/1 are [., ., ., o, o, ., o, o]
# >> *** Neighbors of 2/1 are [., ., ., ., ., o, o, .]
# >> *** Neighbors of 3/1 are [., ., ., o, ., o, ., .]
# >> *** Neighbors of 4/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/2 are [., o, ., ., o, ., ., o]
# >> *** Neighbors of 1/2 are [o, ., o, ., o, ., o, .]
# >> *** Neighbors of 2/2 are [., o, ., o, ., o, ., .]
# >> *** Neighbors of 3/2 are [o, ., ., o, ., ., ., .]
# >> *** Neighbors of 4/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/3 are [., ., o, ., o, ., ., .]
# >> *** Neighbors of 1/3 are [., o, o, ., ., ., ., .]
# >> *** Neighbors of 2/3 are [o, o, ., o, ., ., ., .]
# >> *** Neighbors of 3/3 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 4/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/4 are [., ., o, ., ., ., ., .]
# >> *** Neighbors of 1/4 are [., o, ., ., ., ., ., .]
# >> *** Neighbors of 2/4 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 3/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/7 are [., ., ., ., ., ., ., .]
# >> ........
# >> ..o.....
# >> o.o.....
# >> .oo.....
# >> ........
# >> ........
# >> ........
# >> ........
# >> 
# >> *** Neighbors of 0/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/0 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 2/0 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 3/0 are [., ., ., ., ., o, ., .]
# >> *** Neighbors of 4/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/0 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/1 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 1/1 are [., ., ., ., o, o, ., o]
# >> *** Neighbors of 2/1 are [., ., ., ., ., ., o, .]
# >> *** Neighbors of 3/1 are [., ., ., o, ., o, ., .]
# >> *** Neighbors of 4/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/1 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/2 are [., ., ., ., ., ., ., o]
# >> *** Neighbors of 1/2 are [., ., o, o, o, ., o, o]
# >> *** Neighbors of 2/2 are [., o, ., ., ., o, o, .]
# >> *** Neighbors of 3/2 are [o, ., ., o, ., o, ., .]
# >> *** Neighbors of 4/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/2 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/3 are [., o, ., ., o, ., ., .]
# >> *** Neighbors of 1/3 are [o, ., o, ., o, ., ., .]
# >> *** Neighbors of 2/3 are [., o, ., o, ., ., ., .]
# >> *** Neighbors of 3/3 are [o, ., ., o, ., ., ., .]
# >> *** Neighbors of 4/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/3 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/4 are [., ., o, ., ., ., ., .]
# >> *** Neighbors of 1/4 are [., o, o, ., ., ., ., .]
# >> *** Neighbors of 2/4 are [o, o, ., ., ., ., ., .]
# >> *** Neighbors of 3/4 are [o, ., ., ., ., ., ., .]
# >> *** Neighbors of 4/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/4 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/5 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/6 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 0/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 1/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 2/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 3/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 4/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 5/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 6/7 are [., ., ., ., ., ., ., .]
# >> *** Neighbors of 7/7 are [., ., ., ., ., ., ., .]
# >> ........
# >> .o......
# >> ..oo....
# >> .oo.....
# >> ........
# >> ........
# >> ........
# >> ........

There are a few different ways to do this, but I think one of the simplest is probably to monkey-patch puts in such a way that it checks where it is being called from. I'll define it such that it uses the caller method to get information about the current call stack. When it finds itself invoked from within the game of life code, it will raise an exception; otherwise it'll fall back to the default puts behavior.

Once again, running the code produces an exception that points the way straight back to the debug code I'm trying to track down. I eliminate the debug code, and when I run the script again I have nice clean output.

require './mildly-functional-gol'

glider = <<END
.o......
..o.....
ooo.....
........
........
........
........
........
END

module Kernel
  alias_method :orig_puts, :puts
  def puts(*args)
    if caller[0].include?('mildly-functional-gol.rb')
      raise Exception, 'debug output!'
    else
      orig_puts(*args)
    end
  end
end

board = BoardGeneration.new(glider)
puts board = board.next_generation
puts
puts board = board.next_generation
puts
puts board = board.next_generation

# ~> -:18:in `puts': debug output! (Exception)
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:36:in `neighbors'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:106:in `next_generation'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:83:in `block (2 levels) in next_grid_generation'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:82:in `map'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:82:in `each_with_index'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:82:in `block in next_grid_generation'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:81:in `map'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:81:in `each_with_index'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:81:in `next_grid_generation'
# ~>    from /home/avdi/Dropbox/rubytapas/123-removing-debug-output/mildly-functional-gol.rb:25:in `next_generation'
# ~>    from -:26:in `<main>'
# >> [., o, ., ., ., ., ., .]
# >> [., ., o, ., ., ., ., .]
# >> [o, o, o, ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
# >> [., ., ., ., ., ., ., .]
require './mildly-functional-gol'

glider = <<END
.o......
..o.....
ooo.....
........
........
........
........
........
END

module Kernel
  alias_method :orig_puts, :puts
  def puts(*args)
    if caller[0].include?('mildly-functional-gol.rb')
      raise Exception, 'debug output!'
    else
      orig_puts(*args)
    end
  end
end

board = BoardGeneration.new(glider)
puts board = board.next_generation
puts
puts board = board.next_generation
puts
puts board = board.next_generation

# >> ........
# >> o.o.....
# >> .oo.....
# >> .o......
# >> ........
# >> ........
# >> ........
# >> ........
# >> 
# >> ........
# >> ..o.....
# >> o.o.....
# >> .oo.....
# >> ........
# >> ........
# >> ........
# >> ........
# >> 
# >> ........
# >> .o......
# >> ..oo....
# >> .oo.....
# >> ........
# >> ........
# >> ........
# >> ........

Once I see that I've removed all the debugging output, I get rid of the monkey-patched methods. They are strictly temporary code; once they've served their purpose I don't want them being accidentally committed to my version control system.

So there you have it: an easy way to quickly and completely rid your code of unwanted debugging output. Happy hacking!

Responses