by Jach | 2025-09-08 10:40:45+00:00
In actual Common Lisp development, code is stored in text files and edited and diffed as text in source controlled repositories. Once code is evaluated by an implementation, it's a different story, but before that there are many formatting options. It's mostly around where to put line breaks, whitespace, and parens, but still. The other day I wrote this simple function:

(defun check-password-against-hash (password hash) (handler-case (bcrypt:password= password hash) (error () nil)))

There's already multiple choices on formatting (and naming, and other things) just from this sample.

In theory a system could be made where this level of code isn't what's actually stored and is just a reverse pretty-print-with-my-preferences version of the code, as the post mentions. SBCL compiles my function when I enter it, I can ask SBCL to describe it back to me:

* (describe #'check-password-against-hash) #<FUNCTION CHECK-PASSWORD-AGAINST-HASH> [compiled function] Lambda-list: (PASSWORD HASH) Derived type: (FUNCTION (T T) *) Source form: (LAMBDA (PASSWORD HASH) (BLOCK CHECK-PASSWORD-AGAINST-HASH (HANDLER-CASE (CL-BCRYPT:PASSWORD= PASSWORD HASH) (ERROR NIL NIL))))

I can also ask SBCL to show me the disassembly, perhaps again in theory a system could be made where you can get and edit text at that level of abstraction before putting it back in.

* (disassemble #'check-password-against-hash) ; disassembly for CHECK-PASSWORD-AGAINST-HASH ; Size: 308 bytes. Origin: #xB8018AA278 ; CHECK-PASSWORD-AGAINST-HASH ; 278: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer ; 27C: 488945F8 MOV [RBP-8], RAX ; 280: 488965D8 MOV [RBP-40], RSP ; 284: 488D45B0 LEA RAX, [RBP-80] ; 288: 4D8B7520 MOV R14, [R13+32] ; thread.current-unwind-protect-block ; 28C: 4C8930 MOV [RAX], R14 ; ... and so on ....

(SBCL does actually let you modify the compiled code directly if you felt the urge to do such a thing. You just get a pointer to the given origin address and offset and write away.)

But just going back to the Lisp source form, it's close enough that you could recover the original and format it a few different ways depending on different preferences. e.g. someone might prefer the first expression given to handler-case to be on the same line instead of a new line like I did. But to such a person, is that preference universal, or does it depend on the specific expressions involved? There are other not strictly formatting preferences at play here too, like the use of "cl-bcrypt" vs "bcrypt" as package name, or one could arrange to have no explicit package name at all. My own preferences on both matters are context-sensitive. The closest universal preference I have around this general topic is that I really hate enforced format tools even if they bent to my specific desires 100% of the time.

I'd say the closest modern renditions of what the post is talking about are expressed by node editors. Unreal's Blueprints or Blender's shader editor are two examples, ETL tools are another. But people tend to work at the node level (and may have formatting arguments about the node layout) rather than a pretty-printed text representation of the same data. I think in the ETL world it's perhaps more common to go under the hood a little and edit some text representation, which may be an XML file (and XML can be pretty-printed for many different preferences) or a series of SQL statements or something CSV or INI like... whether or not that text is a 'canonical' representation or a projection would depend on the tool.