Introduction to REPL
Developers like to “move fast and break things.” Well, we like to move fast anyway. A “REPL” is a tool I’ve found that prevents me from getting bogged down working within the context of a large application. Of course, at some point, my new feature or bugfix has to be integrated into the codebase, but starting there adds friction and slows me down. In this post, you’ll learn about what REPLs are, and how to use them to work efficiently.
A REPL is a Read-Evaluate-Print Loop. This concept was first introduced in the Lisp programming language, to allow quick experiments in Lisp. In Lisp, the following is an implementation of a basic REPL:
<span>(</span><span>loop</span> <span>(</span><span>print</span> <span>(</span><span>eval</span> <span>(</span><span>read</span><span>))))</span><span>(</span><span>loop</span> <span>(</span><span>print</span> <span>(</span><span>eval</span> <span>(</span><span>read</span><span>))))</span>(loop (print (eval (read))))
Enter fullscreen mode Exit fullscreen mode
Reading the commands from the inside out (which is how they are executed in Lisp), you can see where REPL gets its name!
Generally speaking, you invoke a REPL from the command line. When you start up a REPL, it will take you to a new interface, similar to a command line, but your instructions are interpreted in the language of the REPL. In fact, you can think of a command prompt as a REPL for Bash. Once in a REPL, you can run commands, define variables, write functions, etc. and see the results.
Examples: Python and Node
Both Python and Node come with fairly sophisticated REPLs when you install them. Here are some examples you can try!
Python
Start up the Python REPL, by typing python3
at your command prompt (in this case, user@comp ~$
) and pressing enter. It will print out some information on your python
installation, and leave you at the REPL prompt (the >>>
):
user@comp ~<span>$ </span>python3Python 3.6.1 <span>(</span>default, Apr 4 2017, 09:36:47<span>)</span><span>[</span>GCC 4.2.1 Compatible Apple LLVM 7.0.2 <span>(</span>clang-700.1.81<span>)]</span> on darwinType <span>"help"</span>, <span>"copyright"</span>, <span>"credits"</span> or <span>"license"</span> <span>for </span>more information.<span>>>></span>user@comp ~<span>$ </span>python3 Python 3.6.1 <span>(</span>default, Apr 4 2017, 09:36:47<span>)</span> <span>[</span>GCC 4.2.1 Compatible Apple LLVM 7.0.2 <span>(</span>clang-700.1.81<span>)]</span> on darwin Type <span>"help"</span>, <span>"copyright"</span>, <span>"credits"</span> or <span>"license"</span> <span>for </span>more information. <span>>>></span>user@comp ~$ python3 Python 3.6.1 (default, Apr 4 2017, 09:36:47) [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>>
Enter fullscreen mode Exit fullscreen mode
From here, you can perform computations, define variables and functions, etc:
<span>>>></span> <span>1</span><span>+</span><span>1</span><span>2</span><span>>>></span> <span>greeting</span> <span>=</span> <span>'hello world'</span><span>>>></span> <span>print</span><span>(</span><span>greeting</span><span>)</span><span>hello</span> <span>world</span><span>>>></span> <span>def</span> <span>print_greeting</span><span>(</span><span>greeting</span><span>):</span><span>...</span> <span>print</span><span>(</span><span>greeting</span><span>)</span><span>...</span><span>>>></span> <span>print_greeting</span><span>(</span><span>'hello world'</span><span>)</span><span>hello</span> <span>world</span><span>>>></span> <span>print_greeting</span><span>(</span><span>'hello function'</span><span>)</span><span>hello</span> <span>function</span><span>>>></span> <span>1</span><span>+</span><span>1</span> <span>2</span> <span>>>></span> <span>greeting</span> <span>=</span> <span>'hello world'</span> <span>>>></span> <span>print</span><span>(</span><span>greeting</span><span>)</span> <span>hello</span> <span>world</span> <span>>>></span> <span>def</span> <span>print_greeting</span><span>(</span><span>greeting</span><span>):</span> <span>...</span> <span>print</span><span>(</span><span>greeting</span><span>)</span> <span>...</span> <span>>>></span> <span>print_greeting</span><span>(</span><span>'hello world'</span><span>)</span> <span>hello</span> <span>world</span> <span>>>></span> <span>print_greeting</span><span>(</span><span>'hello function'</span><span>)</span> <span>hello</span> <span>function</span>>>> 1+1 2 >>> greeting = 'hello world' >>> print(greeting) hello world >>> def print_greeting(greeting): ... print(greeting) ... >>> print_greeting('hello world') hello world >>> print_greeting('hello function') hello function
Enter fullscreen mode Exit fullscreen mode
Exit with ^d
(ctrl+d)
<span>>>></span> ^duser@comp ~<span>$</span><span>>>></span> ^d user@comp ~<span>$</span>>>> ^d user@comp ~$
Enter fullscreen mode Exit fullscreen mode
Node
Enter the Node REPL
user@comp ~<span>$ </span>node<span>></span>user@comp ~<span>$ </span>node <span>></span>user@comp ~$ node >
Enter fullscreen mode Exit fullscreen mode
Just like in Python, you can perform computations, define variables and functions, etc:
<span>></span> <span>1</span><span>+</span><span>1</span><span>2</span><span>></span> <span>const</span> <span>greeting</span> <span>=</span> <span>'</span><span>hello world</span><span>'</span><span>;</span><span>undefined</span><span>></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>greeting</span><span>);</span><span>hello</span> <span>world</span><span>undefined</span><span>></span> <span>const</span> <span>printGreeting</span> <span>=</span> <span>(</span><span>greeting</span><span>)</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>greeting</span><span>);</span><span>undefined</span><span>></span> <span>printGreeting</span><span>(</span><span>'</span><span>hello world</span><span>'</span><span>);</span><span>hello</span> <span>world</span><span>undefined</span><span>></span> <span>printGreeting</span><span>(</span><span>'</span><span>hello function</span><span>'</span><span>);</span><span>hello</span> <span>function</span><span>undefined</span><span>></span> <span>1</span><span>+</span><span>1</span> <span>2</span> <span>></span> <span>const</span> <span>greeting</span> <span>=</span> <span>'</span><span>hello world</span><span>'</span><span>;</span> <span>undefined</span> <span>></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>greeting</span><span>);</span> <span>hello</span> <span>world</span> <span>undefined</span> <span>></span> <span>const</span> <span>printGreeting</span> <span>=</span> <span>(</span><span>greeting</span><span>)</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>greeting</span><span>);</span> <span>undefined</span> <span>></span> <span>printGreeting</span><span>(</span><span>'</span><span>hello world</span><span>'</span><span>);</span> <span>hello</span> <span>world</span> <span>undefined</span> <span>></span> <span>printGreeting</span><span>(</span><span>'</span><span>hello function</span><span>'</span><span>);</span> <span>hello</span> <span>function</span> <span>undefined</span>> 1+1 2 > const greeting = 'hello world'; undefined > console.log(greeting); hello world undefined > const printGreeting = (greeting) => console.log(greeting); undefined > printGreeting('hello world'); hello world undefined > printGreeting('hello function'); hello function undefined
Enter fullscreen mode Exit fullscreen mode
Exit with ^d
(ctrl+d)
<span>></span> ^duser@comp ~<span>$</span><span>></span> ^d user@comp ~<span>$</span>> ^d user@comp ~$
Enter fullscreen mode Exit fullscreen mode
The undefined
that crops up in the Node example is the return value of each statement. If your statement has a defined return value, that will be printed instead, as in the 1+1
example. Note also that these REPLs have command history, so you can press “up” to view past commands, even between sessions.
Implementation
The REPL is just like any program that you run from your command line. When you run it, it gives some output and then waits for user input. When a statement is entered, it evaluates the statement, and prints out the result. In both Python and Node, there are built-in modules that can provide a REPL with some injected “context”. You can read @rpalo ’s excellent post here for how to make use of the Python library Code
to create your own REPL. Here’s how to do it in Node:
<span>// include the repl library</span><span>const</span> <span>repl</span> <span>=</span> <span>require</span><span>(</span><span>'</span><span>repl</span><span>'</span><span>);</span><span>// start it up, with the desired prompt string</span><span>const</span> <span>r</span> <span>=</span> <span>repl</span><span>.</span><span>start</span><span>(</span><span>'</span><span>> </span><span>'</span><span>);</span><span>// inject a couple pieces of context</span><span>r</span><span>.</span><span>context</span><span>.</span><span>text</span> <span>=</span> <span>'</span><span>This is some text</span><span>'</span><span>;</span><span>r</span><span>.</span><span>context</span><span>.</span><span>greet</span> <span>=</span> <span>(</span><span>name</span><span>)</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>`hello </span><span>${</span><span>name</span><span>}</span><span>`</span><span>);</span><span>// include the repl library</span> <span>const</span> <span>repl</span> <span>=</span> <span>require</span><span>(</span><span>'</span><span>repl</span><span>'</span><span>);</span> <span>// start it up, with the desired prompt string</span> <span>const</span> <span>r</span> <span>=</span> <span>repl</span><span>.</span><span>start</span><span>(</span><span>'</span><span>> </span><span>'</span><span>);</span> <span>// inject a couple pieces of context</span> <span>r</span><span>.</span><span>context</span><span>.</span><span>text</span> <span>=</span> <span>'</span><span>This is some text</span><span>'</span><span>;</span> <span>r</span><span>.</span><span>context</span><span>.</span><span>greet</span> <span>=</span> <span>(</span><span>name</span><span>)</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>`hello </span><span>${</span><span>name</span><span>}</span><span>`</span><span>);</span>// include the repl library const repl = require('repl'); // start it up, with the desired prompt string const r = repl.start('> '); // inject a couple pieces of context r.context.text = 'This is some text'; r.context.greet = (name) => console.log(`hello ${name}`);
Enter fullscreen mode Exit fullscreen mode
We can save this as my_repl.js
and then start it up and use it as follows (note that text
and greet
are already defined for you because they were injected into the context):
user@comp ~<span>$ </span>node my_repl.js<span>></span>user@comp ~<span>$ </span>node my_repl.js <span>></span>user@comp ~$ node my_repl.js >
Enter fullscreen mode Exit fullscreen mode
<span>></span> <span>1</span><span>+</span><span>1</span><span>2</span><span>></span> <span>text</span><span>'</span><span>This is some text</span><span>'</span><span>></span> <span>greet</span><span>(</span><span>'</span><span>Jon</span><span>'</span><span>)</span><span>hello</span> <span>Jon</span><span>undefined</span><span>></span> <span>const</span> <span>greetAndCompliment</span> <span>=</span> <span>(</span><span>name</span><span>)</span> <span>=></span> <span>{</span><span>...</span> <span>greet</span><span>(</span><span>name</span><span>);</span><span>...</span> <span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>nice code</span><span>'</span><span>);</span><span>...</span> <span>}</span><span>undefined</span><span>></span> <span>greetAndCompliment</span><span>(</span><span>'</span><span>Jon</span><span>'</span><span>)</span><span>hello</span> <span>Jon</span><span>nice</span> <span>code</span><span>undefined</span><span>></span><span>></span> <span>1</span><span>+</span><span>1</span> <span>2</span> <span>></span> <span>text</span> <span>'</span><span>This is some text</span><span>'</span> <span>></span> <span>greet</span><span>(</span><span>'</span><span>Jon</span><span>'</span><span>)</span> <span>hello</span> <span>Jon</span> <span>undefined</span> <span>></span> <span>const</span> <span>greetAndCompliment</span> <span>=</span> <span>(</span><span>name</span><span>)</span> <span>=></span> <span>{</span> <span>...</span> <span>greet</span><span>(</span><span>name</span><span>);</span> <span>...</span> <span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>nice code</span><span>'</span><span>);</span> <span>...</span> <span>}</span> <span>undefined</span> <span>></span> <span>greetAndCompliment</span><span>(</span><span>'</span><span>Jon</span><span>'</span><span>)</span> <span>hello</span> <span>Jon</span> <span>nice</span> <span>code</span> <span>undefined</span> <span>></span>> 1+1 2 > text 'This is some text' > greet('Jon') hello Jon undefined > const greetAndCompliment = (name) => { ... greet(name); ... console.log('nice code'); ... } undefined > greetAndCompliment('Jon') hello Jon nice code undefined >
Enter fullscreen mode Exit fullscreen mode
Everyday Uses
I find REPLs most useful when trying out a simple experiment. For example, instead of creating a test.py
script to confirm that default parameters work the way I think they do, I can just fire up the REPL and confirm it:
<span>>>></span> <span>def</span> <span>print_greeting</span><span>(</span><span>greeting</span><span>=</span><span>'hello world'</span><span>):</span><span>...</span> <span>print</span><span>(</span><span>greeting</span><span>)</span><span>...</span><span>>>></span> <span>print_greeting</span><span>()</span><span>hello</span> <span>world</span><span>>>></span> <span>print_greeting</span><span>(</span><span>'hello overridden default'</span><span>)</span><span>hello</span> <span>overridden</span> <span>default</span><span>>>></span> <span>def</span> <span>print_greeting</span><span>(</span><span>greeting</span><span>=</span><span>'hello world'</span><span>):</span> <span>...</span> <span>print</span><span>(</span><span>greeting</span><span>)</span> <span>...</span> <span>>>></span> <span>print_greeting</span><span>()</span> <span>hello</span> <span>world</span> <span>>>></span> <span>print_greeting</span><span>(</span><span>'hello overridden default'</span><span>)</span> <span>hello</span> <span>overridden</span> <span>default</span>>>> def print_greeting(greeting='hello world'): ... print(greeting) ... >>> print_greeting() hello world >>> print_greeting('hello overridden default') hello overridden default
Enter fullscreen mode Exit fullscreen mode
Wrap Up
Now that you’ve learned about REPLs, you might also be interested in unit tests, and Test-Driven Development, or TDD. These increase developer velocity in a similar way, by shortening cycle time. They have the added advantage of increasing code quality. For further reading and REPLing, check out the Wikipedia page or repl.it.
Thanks for reading!
暂无评论内容