Episode 013: Connect the REPL
► Play EpisodeNate continues to explore the REPL by gluing it to his editor to see what happens.
- We revisit Tic-Tac-Toe and change it using our new REPL superpowers.
- Let's add request logging to the play endpoint:
/play?row=0&col=1
. - Need to add
log/info
calls in handler function for play endpoint:on-play
. - Naive Christoph would add logging to the function, recompile, and run the jar.
- Less naive Christoph would reload the namespace but still restart the web server.
- Crazy idea: paste the function definition into the REPL!
- Copy the whole
defn
foron-play
- Go to the REPL window
- Switch to the
app.main
namespace (where we puton-play
) - Paste the function definition into the REPL
- Copy the whole
- No restarting required! Each time we evalute the
defn
in the REPL, the new function replaces the old version immediately! - We can iterate on a single function quickly.
- Clojure is Lisp, and Lisp is dynamic and isomorphic
- Dynamic: can change definition on the fly, so the new function exists immediately after executing the definition
- Isomorphic: everything is a "form". No special "declaration syntax" vs "expression syntax". A declaration is a form just like any other expression.
- "Clojure is dynamic to the end. Every statement is modifying the running application, and because every statement has access to the entire application, all the way down to the definitions, you can redefine on the fly."
- Declarations are just ordinary macros (
def
,defn
,defmacro
, etc), not special syntax only the compiler understands. - A declaration macro updates the enclosing namespace dynamically on the fly!
- "You just replaced the wheels on the car while you were driving."
- "I can replace the steering wheel and my hands don't even realize they're using a new steering wheel."
- "Running the form is what brings that thing dynamically into existence or replaces the one that was there."
- "It's the way you can speed your development up because you can replace these functions on the fly."
- Problem: you have to copy and paste between the editor and the REPL.
- Idea: use terminal automation to help with the copy + paste!
- "Yet another example of solving a problem you probably shouldn't even have."
- Pre-Lisp thinking: "The right way to do software is to compile it from grains of sand each and every time, and then run it from the beginning."
- Better Idea: Connect the REPL directly to your editor. (See "More reading" for how.)
- How it works:
- Move your cursor to the form to evaluate
- Do the "right" key combo (depends on your editor)
- Editor sends the form to the REPL
- REPL evaluates the form and sends the result back
- Editor shows the result
- Use
comment
blocks as a nifty way to provide executable examples within the code. - Your editor is a first-class REPL.
Related episodes:
More reading:
Clojure in this episode:
ns
,in-ns
,use
*ns*
,ns-map
def
,defn
comment
let
println
clojure.tools.logging/debug
Related projects:
- clojure.tools.logging for application logging
- vim-fireplace for VIM connected REPL
- Cider for Emacs connected REPL
- Ring for HTTP
- Compojure for HTTP request routing