[racket] Advice how to refactor code to share pattern variables but split out templates?

From: Greg Hendershott (greghendershott at gmail.com)
Date: Wed Sep 4 20:37:08 EDT 2013

Given some macros that are wrappers around a core helper function:

(define-syntax (wrapper1 stx)
  (core #f #f))
(define-syntax (wrapper2 stx)
  (core #f #t))
(define-syntax (wrapper3 stx)
  (core #t #f))
(define-syntax (wrapper4 stx)
  (core #t #t))

(define-for-syntax (core stx opt1? opt2?)
  (define-syntax-class x ....)
  (syntax-parse stx
    [(_ pattern )
     (with-syntax*
       ([ <bunch of pattern variables> ])
       ;; Ugly cond using opt1? and opt2
       (cond [opt1? (cond [opt2? #'( <use ptn vars> )]
                          [else #'( <use ptn vars> )])]
             [else (cond [opt2? #'( <use ptn vars> )]
                         [else #'( <use ptn vars> )])]))]))

Now I want/need to refactor the code. For one thing, some of the
wrappers must be in a file with `#lang racket`, and others in another
file with `#lang typed/racket`. Plus, the cond stuff is ugly; each
wrapper should handle this itself.  And in refactoring, of course I
want to D.R.Y. instead of copy pasta.

The following seems somewhat better. Have the wrappers supply a
"callback" function to the core:

;; wrap12.rkt
#lang racket
(require "core.rkt")
(define-syntax (wrapper1 stx)
  (core (lambda (stx <bunch of pattern vars> )
          #'( <use ptn vars> ))))
.. wrapper2 similar ..

;; wrap34.rkt
#lang typed/racket
(require "core.rkt")
... wrappers 3 4 similar ..

;; core.rkt
(provide core)
(define-for-syntax (core stx f)
  (define-syntax-class y ....)
  (syntax-parse stx
    [(_ pattern )
     (with-syntax*
       ([ <bunch of pattern variables> ])
       (f stx <bunch of pattern variables> ))])) ;; give back to the
caller and let it make the syntax

And now it's easy for them to be in different files. However:

1. Now instead the ugly part is schlepping the pattern variables
around (e.g. half dozen function parameters).

2. Pattern variables and templates can't be separated like this and
still work, AFAICT.

I have a few ideas that I'll go ahead and try, but I wanted to go
ahead and post this to see what ideas or advice anyone might have.


p.s. In case my question and code sketch here is too abstract, my
motivating full example is this:

https://github.com/greghendershott/def-jambda/blob/50f6abcb7a64558756dce653c1faac4c012d4167/main.rkt

Posted on the users mailing list.