(define-macro (def-choice name proc ls)
  (let ((varname (gensym))
        (valname (gensym)))
    (let1 varname (string->symbol #`",|name|s")
      `(begin
         (define-values (,name ,(string->symbol #`"push-,|varname|!"))
           (let1 ,varname ,ls
             (values (lambda ()
                       (,proc ,varname))
                     (lambda (,valname)
                       (push! ,varname ,valname)))))))))

(def-choice adj one-of '(big))
(def-choice prep one-of '(to))

(sentence)
;; (the big man to the ball to a big big big big big woman to a big woman to the table to a big big man to a big big big table to a big big man to the table to the big man to a ball to a table to a man saw a big big big big woman)
(sentence)
;; (the big big ball to a man took a big man)


(push-adjs! 'little)
;; (little big)
(push-adjs! 'blue)
;; (blue little big)
(push-adjs! 'red)
;; (red blue little big)

(sentence)
;; (the blue man to the big table liked the little little table to the big little big big blue little table)
(sentence)
;; (a red little woman hit the red table to a table to the ball to the blue ball)


(push-preps! 'by)
;; (by to)
(push-preps! 'in)
;; (in by to)
(push-preps! 'with)
;; (with in by to)
(push-preps! 'on)
;; (on with in by to)


(sentence)
;; (the table saw a little ball)
(sentence)
;; (the big table to the little man saw a little ball on the big table in the ball)
(sentence)
;; (a little table hit the woman with a table with the red little woman by the red big ball to a ball by the red big big ball with the red table on the big blue red red ball)