add RDD breakdown

This commit is contained in:
2026-09-14 08:20:13 -09:00
parent 1b9dcba220
commit a9bf3c2b73
2 changed files with 227 additions and 0 deletions
+15
View File
@@ -0,0 +1,15 @@
# teach
Clojure learning materials and examples.
## Table of Contents
- [learnclj.clj](learnclj.clj) — Comprehensive Clojure reference with examples covering basics to advanced topics
- [repl.md](repl.md) — Guide to REPLs, starting a Babashka nREPL server, and REPL-driven development
## Files
| File | Description |
|------|-------------|
| `learnclj.clj` | Clojure learning reference covering literals, data structures, control flow, destructuring, protocols, records, state, Java interop, threading macros, and more |
| `repl.md` | Explains what a REPL is, how to start a Babashka nREPL server, and how REPL-driven development works |
+212
View File
@@ -0,0 +1,212 @@
# REPL-Driven Development
## What is a REPL?
A **REPL** is an acronym for **Read-Eval-Print Loop**. It is an interactive programming environment where code is parsed, executed, and results are printed back — in a continuous cycle.
The four stages of the REPL cycle:
1. **Read** — Your input is parsed into a data structure (in Clojure, into a form)
2. **Eval** — The form is evaluated/executed
3. **Print** — The result is printed back to you
4. **Loop** — It goes back to step 1, ready for your next input
Think of it like a conversation with the language. You say something, it responds, you say something else, it responds — but you're programming.
### Why REPLs Matter
REPLs enable **immediate feedback**. Instead of writing a file, compiling, running, seeing an error, fixing, and repeating — you evaluate something and see the result instantly. This dramatically speeds up learning and development.
## REPL-Driven Development (RDD)
**REPL-Driven Development** is a workflow where you build and explore your program by sending code from your editor to a running REPL, rather than through a traditional edit-compile-run cycle.
### The Editor as Your REPL Interface
In the real world, you don't type into a terminal REPL. You use your **editor as the REPL interface**:
- **Calva** (VS Code) — sends code from your buffer to a connected nREPL, shows results inline
- **CIDER** (Emacs) — sends code from your buffer to a connected nREPL, shows results in a REPL buffer
- **Conjure** (NeoVim) — sends code from your buffer to a connected nREPL, shows results inline
- **vim-fireplace** (Vim) — another popular vim Clojure integration
- **Cursive** (IntelliJ) — full Clojure IDE with REPL, autocomplete, and debugging
- **Deps-new / Shadow-cljs / etc.** — other editor integrations via nREPL
Your editor becomes the workspace. You write code, evaluate pieces of it, inspect results, iterate — all without leaving your editing environment.
### How It Works
1. **Start an nREPL server** (one time) — a background process that listens for connections
2. **Connect your editor** to the nREPL — your editor sends code to the REPL, receives results
3. **Edit and evaluate** — write code in your editor, send it to the REPL with a keystroke
4. **Explore and iterate** — try ideas, redefine functions, inspect data, all in real time
5. **Keep state** — your atoms, bindings, and defined functions persist in the REPL session
6. **Save working code** — the code that works in the REPL lives in your source files
### The REPL as a Workspace
The REPL is your **working environment**, not just a debugging tool. Key advantages:
- **Live exploration** — evaluate a function call before you've even written the function
- **Partial implementation** — stub out functions and test the parts that exist
- **Refactoring** — redefine a function and immediately see the impact everywhere
- **Debugging** — inspect intermediate values, bind names to data, step through logic
- **Composition** — build complex logic by combining small tested pieces in the REPL
### RDD Workflow in Practice
With your editor connected to an nREPL server, your workflow looks like this:
```clojure
;; 1. Load your namespace (once, from your editor)
(require '[learnclj :as lc])
(in-ns 'learnclj)
;; 2. Explore existing functions — evaluate from your editor
(greet "Alice")
;; => "Hello, Alice!"
;; 3. Try something new — send a form to the REPL from your editor
(map #(str (upper-case %) "!") ["hello" "world"])
;; => ("HELLO!" "WORLD!")
;; 4. Define a new helper — write it in your buffer, evaluate it
(defn exclaim [s] (str (str/upper-case s) "!"))
(exclaim "hello")
;; => "HELLO!"
;; 5. Refactor — change the definition in your buffer, re-evaluate
(defn exclaim [s] (str (str/upper-case s) "!!"))
(exclaim "hello")
;; => "HELLO!!"
;; 6. Compose with existing code
(map exclaim ["a" "b" "c"])
;; => ("A!!" "B!!" "C!!")
;; 7. The working code is already in learnclj.clj — your source files
```
Your editor sends each form to the REPL. The REPL returns results to your editor. You iterate until satisfied. The code you wrote and tested *is* your source code.
### Key Principles
- **Keep the nREPL running** — don't restart it unnecessarily. State persists.
- **Explore before you commit** — try ideas in the REPL to validate them before writing them into source
- **Small steps** — each form you send should be small enough to understand instantly
- **Don't over-rely on the REPL** — eventually the REPL code should live in source files for reproducibility and version control
- **Use `clojure.repl` functions** — `doc`, `find-doc`, `apropos`, `source` are invaluable
- **Your editor is the interface** — learn the send/eval shortcuts for your editor (Calva, CIDER, etc.)
## Starting an nREPL Server
### Babashka (lightweight, fast)
Babashka is a fast, lightweight Clojure interpreter with built-in nREPL support.
```bash
# Start nREPL server (default port 1667)
bb --nrepl-server
# Specify a port
bb --nrepl-server --nrepl-port 9999
```
**Why Babashka nREPL?**
- **Fast startup** — near-instant compared to full Clojure/JVM
- **No JVM dependency** — uses GraalVM native image, so no Java needed
- **Script-friendly** — works with `.clj` files directly
- **Full nREPL protocol** — compatible with all nREPL clients
### Clojure (JVM-based)
```bash
clj -A:nrepl
```
This starts a Clojure REPL with nREPL support. For a server:
```bash
clj -M:nrepl-server
```
### Connecting from Your Editor
#### Calva (VS Code)
1. Start an nREPL server (`bb --nrepl-server` or `clj -A:nrepl`)
2. `Ctrl+Alt+C, Ctrl+Alt+P` — Calva connects automatically
#### Conjure (NeoVim)
1. Install Conjure via your plugin manager (`vim-plug`, `packer`, `lazy`, etc.)
2. Start an nREPL server (`bb --nrepl-server` or `clj -A:nrepl`)
3. `:ConjureConnect localhost <port>` — connect to the REPL
4. Send code with `,e` (evaluate current line/form)
5. Results appear inline below the code
6. Open the REPL buffer with `:ConjureShow`
**Key Conjure shortcuts:**
- `<localleader>ee` — evaluate form under cursor
- `<localleader>E` — evaluate current line/buffer
- `<localleader>pp` — evaluate and print (with pprint)
- `<localleader>dd` — evaluate and doc
- `<localleader>oo` — open result in browser (for HTML, URLs, etc.)
- `K` — doc word under cursor (built-in, no prefix)
> Note: `<localleader>` defaults to `,` but is typically remapped in your config (e.g., to `\` or `Space`). Check `:map <localleader>` to see yours.
- `:ConjureConnect` — connect to an nREPL server
- `:ConjureShow` — show the REPL buffer
- `:ConjureClear` — clear the REPL buffer
#### vim-fireplace (Vim)
1. Install via your plugin manager
2. Start an nREPL server
3. `:PlFigConnect localhost <port>` — connect
4. Evaluate with `<leader>a` (send current form)
5. Results appear in a split buffer
#### Cursive (IntelliJ IDEA)
1. Install the Cursive plugin (bundled with paid IntelliJ or available as a trial)
2. Start a REPL: `Run → Edit Configurations → + → Local Clojure REPL` — choose your build tool (Leiningen/Deps)
- Or connect to a running REPL: `Run → Edit Configurations → + → Remote Clojure REPL` — enter host/port
3. `Ctrl+Enter` — evaluate form before cursor (works anywhere on the form)
4. `Enter` — execute if cursor is at end of a valid form
5. `Ctrl+Shift+E` — load file in REPL (loads current file + dependencies)
6. `Ctrl+Alt+E` — search REPL history (find and re-execute previous evaluations)
7. `Run → Clojure REPL → Switch REPL Namespace to Current File` — switch the REPL to the file's namespace
**Key features:**
- Full autocomplete with `Ctrl+Space`
- Inline pretty-printed results in the REPL toolwindow
- Debug REPL support — run in debug mode and set breakpoints
- Visual diff of data structures via `(cursive/diff a b)`
- REPL commands — create custom keybindings for common workflows (e.g., reload + evaluate)
#### Calva (VS Code)
1. Start an nREPL server (`bb --nrepl-server` or `clj -A:nrepl`)
2. `Ctrl+Alt+C, Ctrl+Alt+P` — Calva connects automatically
### Loading Your Code
Once connected, load your source files:
```clojure
;; Load learnclj namespace
(require '[learnclj :as lc])
;; Switch to the namespace
(in-ns 'learnclj)
;; Now all functions are available
(greet "Sam")
;; => "Hello, Sam!"
```
## Resources
- [Babashka Docs](https://babashka.org/)
- [Clojure REPL Guide](https://clojure.org/guides/repl/app_dev)
- [Calva](https://calva.io/) — VS Code extension for Clojure
- [CIDER](https://cider.readthedocs.io/) — Emacs Clojure IDE
- [Conjure](https://github.com/Olical/conjure) — Async REPL for NeoVim
- [vim-fireplace](https://github.com/tpope/vim-fireplace) — Vim Clojure integration
- [Repl-Driven Development](https://nakkaya.com/2019/03/12/repl-driven-development/) — detailed article on RDD