How to define subidform - racket

In racket, we have defsubform for subform, but defsubform does not accept a form like bar but only (bar ...)

Here's a (cleaned-up) implementation of defsubform
#lang racket
(require scribble/core
scribble/decode)
(define (into-blockquote s)
(make-nested-flow (make-style "leftindent" null)
(if (splice? s)
(decode-flow (splice-run s))
(list s))))
(define-syntax (defsubform stx)
(syntax-case stx ()
[(_ . rest) #'(into-blockquote (defform . rest))]))
This suggests that you can implement defsubidform as follows:
(define-syntax (defsubidform stx)
(syntax-case stx ()
[(_ . rest) #'(into-blockquote (defidform . rest))]))

Related

Racket: local-expanding recursive definitions

I'm trying to write a macro behaving just like racket define, but processing fully expanded racket procedures in some way (just expanding for simplicity in the example below):
(define-syntax (define/expand stx)
(syntax-case stx ()
[(_ (head args ...) body body-rest ...)
(let* ([define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
[fully-expanded (local-expand define/racket 'top-level (list))])
fully-expanded)]
[(_ id expr) (syntax/loc stx (define id expr))]))
Everything is fine unless recursive definition is met:
(define/expand (sum n)
(if (<= n 0)
0
(+ n (sum (- n 1)))))
Running it raises an error
sum: unbound identifier in module in: sum
pointing the call of the sum (not the definition). Obviously the definition of sum is not captured by local expander. I've tried a straightforward way of fixing it: creating new local definition context and binding head into it:
(define-syntax (define/expand stx)
(syntax-case stx ()
[(_ (head args ...) body body-rest ...)
(let* ([ctx (syntax-local-make-definition-context)] ; <- These two lines added
[_ (syntax-local-bind-syntaxes (list #'head) #f ctx)] ; <--/
[define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
[fully-expanded (local-expand define/racket 'top-level (list) ctx)])
fully-expanded)]
[(_ id expr) (syntax/loc stx (define id expr))]))
It solves the problem (local expanded successfully expands the procedure into define-values), but creates the other one:
module: out-of-context identifier for definition in: sum
pointing the definition of sum. The reason is probably that expander binds identifiers to one in ctx instead of head in current context.
Intuitively it does not seem to be a rare problem, but I could not find the solution over the network. I thought that I should somehow use local-expand/capture-lifts and syntax-local-lift-expression, but I don't get how to use it properly. Could someone clarify what's going on and/or give a hint how to fix it?
Let's try your first program in a top-level (repl):
#lang racket
(define-syntax (define/expand stx)
(syntax-case stx ()
[(_ (head args ...) body body-rest ...)
(let*
([define/racket (syntax/loc stx (define (head args ...) body body-rest ...))]
[fully-expanded (local-expand define/racket 'top-level (list))])
fully-expanded)]
[(_ id expr)
(syntax/loc stx (define id expr))]))
and then in the repl:
Welcome to DrRacket, version 6.6.0.3--2016-07-28(-/f) [3m].
Language: racket, with debugging [custom]; memory limit: 1024 MB.
> (define/expand (sum n)
(if (<= n 0)
0
(+ n (sum (- n 1)))))
.#<syntax:3:2 (define-values (sum) (lambda ...>
> (sum 5)
15
This shows that your program works at the top-level.
The reason the same approach doesn't work in a module context
is that the #%module-begin uses partial expansion of forms
to detect definitions before expanding expressions.
In other words define/expand must tell #%module-begin that
it expands into a definition of sum but must delay the use
of local-expand until #%module-begin has detected all
bound identifiers at the module level.
This suggests a two step approach:
#lang racket
(define-syntax (delay-expansion stx)
(syntax-case stx ()
[(_delay-expansion more ...)
(let ([fully-expanded (local-expand #'(lambda () more ...) 'module (list))])
(display fully-expanded)
fully-expanded)]))
(define-syntax (define/expand stx)
(syntax-case stx ()
[(_ (head args ...) body body-rest ...)
(syntax/loc stx
(define (head args ...)
((delay-expansion
body body-rest ...))))]
[(_ id expr)
(syntax/loc stx
(define id expr))]))
(define/expand (sum n)
(if (<= n 0)
0
(+ n (sum (- n 1)))))
(sum 5)
See more here: https://groups.google.com/d/msg/racket-users/RB3inP62SVA/54r6pJL0wMYJ

syntax-parameter pointing to a syntax-pattern-variable?

The syntax-parameterize is commonly used in conjunction with make-rename-transformer so that the syntax-parameter p behaves as an alias for another identifier:
#lang racket
(require racket/stxparam)
(define-syntax-parameter p #f)
(define-syntax (test-1-p stx)
(syntax-case stx ()
[(_ body)
#'(let ([tmp 123])
(syntax-parameterize ([p (make-rename-transformer #'tmp)])
body))]))
(test-1-p p) ;; prints 123
The code above works well, as tmp is an identifier bound by let. If however I try to make p an alias for the pattern variable tmp bound by with-syntax, then it does not work as expected:
#lang racket
(require racket/stxparam)
(define-syntax-parameter p #f)
(define-syntax (test-2-p stx)
(syntax-case stx ()
[(_ body)
#'(with-syntax ([tmp #'(foo 123)])
(syntax-parameterize ([p (make-rename-transformer #'tmp)])
body))]))
(test-2-p #'p) ;; gives #'p, instead of #'(foo 123)
If instead I declare a p-unhygienic syntax, and bind it to (make-rename-transformer #'tmp), then it works fine:
#lang racket
(define-syntax (test-3-p stx)
(syntax-case stx ()
[(_ body)
#`(with-syntax ([tmp #'(foo 123)])
(define-syntax #,(syntax-local-introduce #'p-unhygienic)
(make-rename-transformer #'tmp))
body)]))
(test-3-p #'p-unhygienic) ;; gives #'(foo 123), as expected
How can I create a hygienic alias for a pattern variable using syntax-parameterize ?
This is an interesting case, I expected the same thing you did. This might be either a bug somewhere or a limitation; I'm not sure. Either way, the define-rename-transformer-parameter form is provided as a workaround.
The initial value of a rename-transformer-parameter must be a rename-transformer, so you can use a p-init identifier with #f as the transformer binding.
(define-syntax p-init #f)
(define-rename-transformer-parameter p (make-rename-transformer #'p-init))
In context:
#lang racket
(require racket/stxparam)
(define-syntax p-init #f)
(define-rename-transformer-parameter p (make-rename-transformer #'p-init))
(define-syntax (test-2-p stx)
(syntax-case stx ()
[(_ body)
#'(with-syntax ([tmp #'(foo 123)])
(syntax-parameterize ([p (make-rename-transformer #'tmp)])
body))]))
(test-2-p #'p) ; #<syntax:10:28 (foo 123)>

Writing a `define-let` macro, with hygiene

I'm trying to write a define-let macro in racket, which "saves" the header of a (let ((var value) ...) ...) , namely just the (var value) ... part, and allows re-using it later on.
The code below works as expected:
#lang racket
;; define-let allows saving the header part of a let, and re-use it later
(define-syntax (define-let stx1)
(syntax-case stx1 ()
[(_ name [var value] ...)
#`(define-syntax (name stx2)
(syntax-case stx2 ()
[(_ . body)
#`(let ([#,(datum->syntax stx2 'var) value] ...)
. body)]))]))
;; Save the header (let ([x "works]) ...) in the macro foo
(define-let foo [x "works"])
;; Use the header, should have the same semantics as:
;; (let ([x "BAD"])
;; (let ([x "works])
;; (displayln x))
(let ([x "BAD"])
(foo (displayln x))) ;; Displays "works".
The problem is that the macro breaks hygiene: as shown in the example below, the variable y, declared in a define-let which is produced by a macro, should be a new, uninterned symbol, due to hygiene, but it manages to leak out of the macro, and it is erroneously accessible in (displayln y).
;; In the following macro, hygiene should make y unavailable
(define-syntax (hygiene-test stx)
(syntax-case stx ()
[(_ name val)
#'(define-let name [y val])]))
;; Therefore, the y in the above macro shouldn't bind the y in (displayln y).
(hygiene-test bar "wrong")
(let ((y "okay"))
(bar (displayln y))) ;; But it displays "wrong".
How can I write the define-let macro so that it behaves like in the first example, but also preserves hygiene when the identifier is generated by a macro, giving "okay" in the second example?
Following the cue "syntax-parameter" from Chris, here is an one solution:
#lang racket
(require racket/stxparam
(for-syntax syntax/strip-context))
(define-syntax (define-let stx1)
(syntax-case stx1 ()
[(_ name [var expr] ...)
(with-syntax ([(value ...) (generate-temporaries #'(expr ...))])
#`(begin
(define-syntax-parameter var (syntax-rules ()))
...
(define value expr)
...
(define-syntax (name stx2)
(syntax-case stx2 ()
[(_ . body)
(with-syntax ([body (replace-context #'stx1 #'body)])
#'(syntax-parameterize ([var (syntax-id-rules () [_ value])] ...)
. body))]))))]))
(define-let foo [x "works"])
(let ([x "BAD"])
(foo (displayln x))) ; => works
(let ([x "BAD"])
(foo
(let ([x "still works"])
(displayln x)))) ; => still works
UPDATE
This solution passes the additional test in the comments.
The new solution transfers the context of the body to
the variables to be bound.
#lang racket
(require (for-syntax syntax/strip-context))
(define-syntax (define-let stx1)
(syntax-case stx1 ()
[(_ name [var expr] ...)
#`(begin
(define-syntax (name stx2)
(syntax-case stx2 ()
[(_ . body)
(with-syntax ([(var ...) (map (λ (v) (replace-context #'body v))
(syntax->list #'(var ...)))])
#'(let ([var expr] ...)
. body))])))]))
(define-let foo [x "works"])
(let ([x "BAD"])
(foo (displayln x))) ; => works
(let ([x "BAD"])
(foo
(let ([x "still works"])
(displayln x)))) ; => still works
(let ([z "cool"])
(foo (displayln z))) ; => cool

Racket Macro How to Pass Ellipses to Helper function?

Given:
(define-syntax (test stx)
(syntax-case stx ()
[(_ body ...)
(with-syntax ([body0 (process-body #'(body ...))])
#'body0)]))
How should I receive the pattern and the ellipses in the helper? I'm not even sure if wrapping the body ... inside () is correct, but I've seen it around and it's the only thing that doesn't crash.
The process-body procedure ends up with syntax that has extra () wrapping it. I can try and break this apart, but I'm just wondering what the correct way to do this is.
process-body wraps the body pattern with some code before AND after. And, similar to define, I want to be able to provide the macro with multiple forms rather than all forms in one list. So, if given (form1) (form2), where form2 is the ellipses, process-body should (do-something) (form1) (form2) (do-something-else).
ie,
(define-for-syntax (process-body body-syntax)
(with-syntax ([stx body-syntax])
(syntax/loc body-syntax
(λ (request)
stx))))
Of course I have this working when I define the template in-line, and I suppose I could do that here, but sometimes the template becomes unwieldy and it's nice to call a helper.
Thanks a lot.
As an edit to try dyoo's first example, I'm providing the following:
#lang racket
(define-syntax (test2 stx)
(syntax-case stx ()
[(_ body ...)
(with-syntax ([(body0 ...) (process-body2 #'(body ...))])
#'(begin body0 ...))]))
(define-for-syntax (process-body2 bodies)
(with-syntax ([(body ...) bodies])
(syntax/loc bodies
(λ (request)
body ...))))
(test2 (print "hi"))
λ: bad syntax
The left hand side of a with-syntax pattern can also have ellipses, so that the following is possible:
(define-syntax (test stx)
(syntax-case stx ()
[(_ body ...)
(with-syntax ([(body0 ...) (process-body #'(body ...))])
#'(begin body0 ...))]))
The basic idea is that if process-body returns the transformed body elements, we can then introduce them all together with a begin.
Your process-body definition can also use with-syntax with ellipses too. So you can do something like this:
(define-for-syntax (process-body bodies)
(with-syntax ([(body ...) bodies])
(syntax/loc bodies
(λ (request)
body ...))))
If that's the definition of process-body, we should amend test since the shape of the result from process-body is now a complete lambda expression, so we can just return its result directly:
(define-syntax (test stx)
(syntax-case stx ()
[(_ body ...)
(process-body (syntax/loc stx (body ...)))]))
As a self-contained example:
#lang racket
(define-syntax (test stx)
(syntax-case stx ()
[(_ body ...)
(process-body
(syntax/loc stx (body ...)))]))
(define-for-syntax (process-body bodies)
(with-syntax ([(body ...) bodies])
(syntax/loc bodies
(λ (request)
(printf "before the body\n")
body ...
(printf "after the body\n")))))
;; Let's try it:
(define p
(test (displayln "hello") (displayln "world")))
(p 'should-be-a-request)

Is it possible to just print the string that was passed into the Scheme macro?

I am working on a language translator in guile scheme, and need to handle the basic case, where you're trying to convert a single word.
(define var 5)
(translate var)
This should return the string var and not the number 5.
How do I do this using R5RS Scheme macros (the define-syntax style)?
Edit:
I'm translating from Scheme to Coffeescript.
(define-syntax translate
(syntax-rules ()
[(_ v) 'v]))
And if you want a string:
(define-syntax translate
(syntax-rules ()
[(_ v) (symbol->string 'v)]))
Hopefully Guile's compiler is smart enough to fold the resulting expression so it essentially becomes a constant string.
With syntax-case and its guard support:
(define-syntax translate
(lambda (stx)
(syntax-case stx ()
[(_ v) (identifier? #'v)
#'(symbol->string 'v)]
[(_ v) (number? (syntax-e #'v))
#'(number->string v)])))
(I've used square brackets for easy comparison with Eli's answer, however, it's not my usual style. ;-))
But if you're using syntax-case, then you can just as well do the conversion at the syntax level instead of producing code that does it at runtime:
(define-syntax translate
(lambda (stx)
(syntax-case stx ()
[(_ v) (identifier? #'v)
(datum->syntax stx (symbol->string (syntax->datum #'v)))]
[(_ v) (number? (syntax-e #'v))
(datum->syntax stx (number->string (syntax->datum #'v)))])))
The main thing here is that the macro code is now plain scheme, for example, you could abstract the common parts into a helper:
(define-syntax translate
(lambda (stx)
(define (rewrap convert x)
(datum->syntax stx (convert (syntax->datum x))))
(syntax-case stx ()
[(_ v) (identifier? #'v) (rewrap symbol->string #'v)]
[(_ v) (number? (syntax-e #'v)) (rewrap number->string #'v)])))
Along the same lines, if this macro is so simple, then there's no real need for syntax-case, other than pulling out the subexpression:
(define-syntax translate
(lambda (stx)
(syntax-case stx ()
[(_ v) (let ([d (syntax->datum #'v)])
(datum->syntax
stx
((cond [(number? d) number->string]
[(symbol? d) symbol->string])
d)))])))
Note, BTW, that there is no magic in syntax-case -- and in the case of this simple pattern, you could just pull out the value yourself:
(define-syntax translate
(lambda (stx)
(let ([d (cadr (syntax->datum #'v))])
(datum->syntax
stx
((cond [(number? d) number->string]
[(symbol? d) symbol->string])
d)))))
There is some boilerplate stuff that syntax-case does that this last version loses:
If you use the macro in an unexpected way like (translate) then this version will throw an error about cadr instead of a more comprehensible syntax error
Similarly, if you use (translate 1 2) then this version will just silently ignore the 2 instead of an error.
And if it's used with something that is neither an identifier nor a number (eg, (translate (+ 1 2))) then this will depend on the unspecified value that cond returns rather than throwing a syntax error.
The other answers are useful enough already, but I thought I'd just point out that it's possible to generalize this technique in a very useful ways: macros to print out expressions and their results for debugging:
(define-syntax log-expr
(syntax-rules ()
((_ expr)
(let ((result expr))
(write (quote expr))
(display " evaluates to ")
(write result)
(newline)
result))))