[ANN] Template Macros: A Toolkit for the Practicing Language-Oriented Programmer

54 views
Skip to first unread message

Eric Griffis

unread,
Mar 17, 2020, 1:30:18 PM3/17/20
to Racket Users
Hello,

I'm pleased to announce the initial release of Template Macros, a Racket library that dramatically simplifies the generation of meta-program code.

https://github.com/dedbox/racket-template

Template macros infiltrate the spaces under-served by Racket's existing pattern-based and procedural macros, such as the insides of literal data,

  > (with-template ([X 1] [Y 2]) (values XY3 "YX0" #rx"^X+Y$"))
  123
  "210"
  #rx"^1+2$"

or in the various quoted forms;

  > (begin-template #'(untemplate (build-list 10 values)))
  #<syntax:stdin::5095 (0 1 2 3 4 5 6 7 8 9)>

and when one template macro is used by another, the results are spliced in place automatically.

  > (begin-template (list (for/template ([K (in-range 10)]) K)))
  '(0 1 2 3 4 5 6 7 8 9)

Template macros eliminate common technical barriers to advanced Racket meta-programming techniques by preempting the default macro expander. The current API offers a lot more than I could jam into a release announcement, and it's still evolving!

In the coming weeks and months, I'll try to post some topic-focused tutorials that highlight the wealth of functionality template macros provide to the practicing language-oriented Racket programmer.

But the next time you trip on a missing syntax-local-introduce,

  > (define-template (urlang-js modpath)
      (let ()
        (local-require (only-in modpath the-javascript))
        (the-javascript)))

or find yourself facing a wall of format-id's,

  > (for*/template ([M (in-range 1 6)]
                    [N (in-range 1 6)])
      (define idMxN '((for/template ([I (in-range 1 (add1 M))])
                        (vector (for/template ([J (in-range 1 (add1 N))])
                                  (if-template (= I J) 1 0))))))
      (when-template (= M N)
        (define idM idMxN)))
  > id5
  '((vector 1 0 0 0 0)
    (vector 0 1 0 0 0)
    (vector 0 0 1 0 0)
    (vector 0 0 0 1 0)
    (vector 0 0 0 0 1))

or struggle to interleave a medley of functions with "syntax" in their names,

  > (define-template (hyphen-define* Names Args Body)
      (define
        #,(string->symbol (string-join (map symbol->string 'Names) "-"))
        (λ Args Body)))
  > (hyphen-define* (foo bar baz) (v) (* 2 v))
  > (foo-bar-baz 50)
  100

give template macros a try and let me know how it goes!

Eric
Reply all
Reply to author
Forward
0 new messages