Exploring is a large part of what programmers do during the time when we're not typing out code. Attempting to discover the correct way to do something, or to get a feeling for how something works is an essential part of the job, and for many people it's also the most fun.
While these aren't the only examples, I classify the following as exploring:
- Trying out new libraries.
- Designing good APIs.
- Debugging existing programs.
- Exploring data sets.
There are several passive ways to solve these tasks. You can try Google, and see if someone else has blogged about the problem, or try reading lots of existing code or documentation in the hope that inspiration strikes. A more active approach however is to write some code.
Exploring with code
Writing code to explore problem domains is the best way to get tangible feedback. If you're designing an API, but don't try using it, your API will not be very good. If you're trying to learn a new library, but don't actually use it, you'll not gain much. Finally, if you are trying to debug without writing code; you are trying to emulate an entire computer with your mind, which is pretty tiring.
The code you write while exploring will be different from the code you write when building applications. Instead of the aim being an application you can deploy, the aim is to improve your mental model. This in turn means that you need to treat code differently: good exploratory code is designed to be written quickly, run once, and to give you plenty of output that you can understand what happened. It's expected to be buggy, and you're expected to just keep adding hacks until it works.
Programming in a REPL
Read-evaluate-print loops are an invaluable tool for exploratory coding. They have features that are so obvious to enable this that you probably didn't notice them before:
- Intermediate values generated are always displayed.
- Running programs can be inspected in arbitrary detail.
- You can always decide which line of code to execute next.
Contrast this to a normal development cycle of using a text-editor and then
running the program from the start. In that process the computer mindlessly
re-evaluates the entire program, dumps out a tiny amount of information at any
Using Pry as a REPL
Pry is a REPL designed with these features in mind. Taking inspiration from Smalltalk and SLIME, it embraces the idea of exploratory programming and helps you to do it more effectively. While it'd take me too long to cover all of its features, here are the two I consider most important:
 pry(main)> ls CodeRay
constants: CODERAY_PATH Duo Encoders FileType GZip Plugin PluginHost Scanners Styles TokenKinds Tokens TokensProxy VERSION WordList
CodeRay.methods: coderay_path encode encode_file encode_tokens encoder get_scanner_options highlight highlight_file scan scan_file scanner
If you've ever wondered what a given object can do, the
ls command will
help you. Additionally, and along with the
command, it can also answer questions like "How do I use this API to achieve X?".
 pry(main)> $ binding.pry
if args.first.is_a?(Hash) || args.length == 0
command, aliased to
$, allows you to see how something is implemented. This is
vital both for debugging, and also for exploring new libraries. The
command can be used in combination to fix bugs you spot on the fly.
Acknowledging the existence of temporary exploratory code as distinct from permanent application code has huge benefits. When you're comfortable with writing code that will be immediately thrown away, you can iterate purposefully to find solutions instead of relying on google and inspiration.
A REPL is the best tool to help you do this. Unlike your text editor which is designed for writing permanent robust code, a REPL is designed to help you write temporary code to quickly understand problem domains. Exploration tasks where this is most helpful include learning new libraries, designing APIs, debugging, data analysis, smoke testing, etc.
Pry is a world-class REPL. It's written in Ruby, and due to its extensive wrapping of Ruby's introspection APIs excels for exploring in Ruby. Due to the JVM's homogeneous object model and JRuby we're also beginning to see Pry used as an exploration tool for non-ruby projects1.
And so that is why you should use Pry :).