Be gentle, folks—first time posting here.
I've been interested in DSLs for a long time, and when I get the itch I come back to Racket to fool around a bit and inevitably find myself tangled up in some issue or another. The TL;DR here is that I'm wondering if it's possible to splice syntax into an existing form of the sort:
(some-function #:some-keyword-arg some-val
(generate-n-function-calls arg1 arg2 arg3))
; Expands to:
; (some-function #:some-keyword-arg some-val
; (some-other-function arg1)
; (some-other-function arg2)
; (some-other-function arg3))
To make it more concrete, I've been working with slideshow. I wish the following were more entertaining, but it represents basically what I'm looking at:
#lang slideshow/widescreen
(slide #:title "Minimal slide"
(item "One")
(item "Two")
(item "Three"))
I'm lazy, so I'd rather write:
#lang slideshow/widescreen
(define (itemize . lst) (map item lst))
(slide #:title "Minimal slide"
(itemize "One" "Two" "Three"))
; => slide*: argument sequence contains a bad element: '(#<pict> #<pict> #<pict>)
Ahhh, I say, so I presumably need to destructure these and maybe make a set of values? (Stare at docs a bit I don't think I want to use 'alts
even though I can make it work. And why is the error coming from slide*
and not slide
? A bit of indirection...)
; ...
(define (itemize . lst) (apply values (map item lst)))
; ...
; => result arity mismatch;
; expected number of values not received
; expected: 1
; received: 3
Huh, ok. A bit weird. Let me make sure that I haven't completely forgotten how values
works:
$ racket -I slideshow
Welcome to Racket v8.2 [cs]
> (apply values (map item '("1" "2" "3")))
#<pict>
#<pict>
#<pict>
Maybe I need to write a syntax transformer that would make this easier? (How naive.)
; I know, let's do this the easy way
(define-syntax-rule (itemize str0 ...)
(begin (item str0) ...)) ; oh macro expansion is so beautiful
(slide #:title "Min slide"
(itemize "1" "2" "3"))
; => ·3; where did ·1 and ·2 go???
; Ohhhh, right begin evaluates and only returns the last form here
So I then reasoned that I needed to splice in the syntax or else write something from the top down, like
(define-syntax (itemized-slide stx)
; exercise left to the reader
#'void)
As soon as I started down this path, I thought this would be a terrible choice: I really just want to use an existing API and not try to get too cute. But now I'm thinking hard about this issue of trying to splice in syntax and thought to approach someone, anyone, who could make this a bit more clear for me. Like all of my trials with define-syntax
, it feels like I immediately hit upon something that will break hygiene and quite possibly the universe.
My intuitions here are usually wrong, and it seems like the sort of simple example where there's a trove of insights waiting to be had.