Skip to content

Instantly share code, notes, and snippets.

@rocketnia
Last active May 23, 2020 04:32
Show Gist options
  • Save rocketnia/ea4eb48897239f9c80bbcc13dd5b2f61 to your computer and use it in GitHub Desktop.
Save rocketnia/ea4eb48897239f9c80bbcc13dd5b2f61 to your computer and use it in GitHub Desktop.
An example of using compound expressions for readability of code-generating code.

I find compound unquoted expressions to be pretty good for the readability of a code generator. I think this is a good example (from the current version of html-render.rkt):

`(div ([class ,(if top?
                   "tocviewlist tocviewlisttopspace"
                   "tocviewlist")])
   ,(if top? `(div ([class "tocviewtitle"]) ,header) header)
   ,(if (null? children)
      ""
      `(div ([class ,(cond
                      [(and top? last?) "tocviewsublistonly"]
                      [top? "tocviewsublisttop"]
                      [last? "tocviewsublistbottom"]
                      [else "tocviewsublist"])]
             [style ,(format "display: ~a;" (if expand? 'block 'none))]
             [id ,id])
         (table ([cellspacing "0"] [cellpadding "0"])
           ,@(for/list ([c children])
               (let-values ([(t n) (toc-item->title+num c #t)])
                 `(tr () (td ([align "right"]) ,@n) (td () ,@t))))))))

From that, I can read off the general structure of the generated code:

tocviewlist
  tocviewtitle (optional wrapper)
    header
  tocviewsublist (optional)
    table
      tr (multiple)
        td
        td

Let's say we pull out each of the unquoted compound expressions into its own definition so that we're only unquoting simple variables. I'll try to be fair and do this in as readable a way as I can imagine, without unnecessarily changing other aspects of the original code.

(define class
  (if top?
      "tocviewlist tocviewlisttopspace"
      "tocviewlist"))

(define title
  (if top? `(div ([class "tocviewtitle"]) ,header) header))

(define (generate-sublist)
  
  (define class
    (cond
     [(and top? last?) "tocviewsublistonly"]
     [top? "tocviewsublisttop"]
     [last? "tocviewsublistbottom"]
     [else "tocviewsublist"]))
  
  (define style (format "display: ~a;" (if expand? 'block 'none)))
  
  (define rows
    (for/list ([c children])
      (let-values ([(t n) (toc-item->title+num c #t)])
        `(tr () (td ([align "right"]) ,@n) (td () ,@t)))))
  
  `(div ([class ,class]
         [style ,style]
         [id ,id])
     (table ([cellspacing "0"] [cellpadding "0"])
       ,@rows)))

(define sublist
  (if (null? children)
    ""
    (generate-sublist)))

`(div ([class ,class])
   ,title
   ,sublist)

Now, if I look for the same landmarks in the code, they're all out of order:

class :=
  tocviewlist

title :=
  tocviewtitle (optional wrapper)
    header

sublist (optional) := {
  class :=
    tocviewsublist
  
  rows :=
    tr (multiple)
      td
      td
  
  class
    table
      rows
}

class
  title
  sublist

I have to do a lot of reconstruction in my mind to get a picture of what the final document would look like.

@rocketnia
Copy link
Author

I've made a mockup of a way quasiquotation code might be made more readable using a second dimension of indentation:

The same code example with the quasiquoted parts extruded from the screen in 3D.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment