Idiomdrottning’s homepage

Wrapping and raising

In the world of 3D-modeling, back in the day before sculpting and retopo were invented, there were two different styles of modeling. Point-by-point (where you create a point, join it up to your other points with a line, and join that line up with your other lines with a face) and box modeling, where you start with a box, and cut and push and add loops to it.

When I’m using paredit to work on Lisp code, I’m using it like a box modeler.

The core primitives for me are wrapping and raising.

I start by inserting an empty pair and as I write, I keep adding pairs in. In the following evolving example, the bar character | represents my cursor.

(|)

(let ((|)))

(let ((foo|)))

(let ((foo (|))))

(let ((foo (bar|))))

(let ((foo (bar (|)))))

(let ((foo (bar (+ 11 12|)))))

(let ((foo (bar (+ 11 12))))|)

(let ((foo (bar (+ 11 12))))
  (|))

(let ((foo (bar (+ 11 12))))
  (frobnicate foo foo|))

So far, so normal. Like any other paredit user. Now let’s say I later realize that I need one of those foos to be reversed.

Let me first show you what I would not do:

(let ((foo (bar (+ 11 12))))
  (frobnicate (|) foo foo))

(let ((foo (bar (+ 11 12))))
  (frobnicate (reverse|) foo foo))

(let ((foo (bar (+ 11 12))))
  (frobnicate (reverse foo|) foo))

Using a forward-slurp-sexp.

Instead, I’d start by wrapping the foo, and then adding the new operator.

(let ((foo (bar (+ 11 12))))
  (frobnicate (|foo) foo))

(let ((foo (bar (+ 11 12))))
  (frobnicate (reverse |foo) foo))

If I later decide I don’t want that foo reversed after all, I can use raise-sexp on it. Wrapping and raising are the core primitives of working with the syntax tree as a tree, always preserving the syntactic structure, as opposed to seeing it just as text that happens to have a matching paren that you want to push rightwards by slurping.

There’s also splicing and splice-killing that are useful.