how can I match a list in syntax parse? I tried this code:
(syntax-parse #'(1 2)
[(list a b) (printf "a: ~a~n") #'a])
but doesn't seem to work. I'm assuming '(1 2) is a list in racket?
The pattern syntax of syntax-parse and match are different.
Try:
(syntax-parse #'(1 2)
[(a b) (printf "a: ~a~n" #'a)])
Related
From https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html#Syntax-Rules I got the following macro example:
(define-syntax simple-let
(syntax-rules ()
((_ (head ... ((x . y) val) . tail)
body1 body2 ...)
(syntax-error
"expected an identifier but got"
(x . y)))
((_ ((name val) ...) body1 body2 ...)
((lambda (name ...) body1 body2 ...)
val ...))))
I am trying to understand how this macro works. So I annotated it a little:
;; EXAMPLE 7
;; Reporting errors at macro-expansion time (read time, compile time).
(define-syntax simple-let
(syntax-rules ()
[(simple-let (head ... ((x . y) val) . tail)
; (1) head ... can also be zero times?
; (2) what is `. tail` matching?
; (3) can I not use two ellipsis on the
; same level instead of `. tail`?
body1
body2 ...)
(syntax-error "expected an identifier but got"
(x . y))]
;; if there ((a . b) val) is not matched
[(simple-let ((name val) ...)
body1
body2 ...)
((lambda (name ...)
body1
body2 ...)
val ...)]))
The only part I do not really understand in terms of how it works is the first match expression:
(simple-let (head ... ((x . y) val) . tail)
So I tried a few examples:
;; simply working
(simple-let ([a 3])
(+ a 4))
;; caught
(simple-let ([(a . b) 3]) ; Q: What is `. tail` matching in this one?
(+ a 4))
(simple-let ([a 3] [(b . c) 3]) ; Q: What is `. tail` matching in this one?
(+ a b))
;; not caught
(simple-let ([a 3] [(b . c) 3] [d 4]) ; Q: Why is `. tail` not matching `[d 4]`?
(+ a b))
I have difficulties understanding what part is . tail matching and why. I tried using ... instead of . and put it behind tail, in order to catch the example where the syntax error is not caught, because it does not go into the first match case, but it does not work and tells me that it is a bad usage of ellipsis. My guess is, that one cannot have two ellipsis in the same nesting level, because it would be hard to know which ellipsis matches what. Kind of like regular expressions become computationally expensive in some cases.
So what does . tail match in the examples and why is that one example not caught?
usually tail matches the rest of the list e.g.
for '(1 2 3 4) matching with the pattern (1 . x), x matches '(2 3 4).
The result is confusing so one need to go to the sources to see the implementaion (see ice-9/psyntax.scm)
There one can see that the ellipsis is translated to (each+ x y z) with z in this case is tail and is matching the last cdr which in all your cases is '().
In the example ... is gready and . tail is not. If you are dissatisfied with how this behavior is documented or want to change the implementation you may ask on the guile-devel mailing list: guile-devel#gnu.org
Guile has also syntax-parse as a downloadable lib (search for guile-syntax-parse) which is a port of racket's syntax-parse as of a couple of years ago (see racket's documentation if you are curious) I coded your example with syntax-parse and that seamed to execute as you expected.
I need to implement my_let* using defmacro which works similarly to let*, but while let* is expanded to a series of nested let calls (behind the scenes), my_let* needs to be expanded to a single let call, and use the define statement to define the arguments i get.
an example of using my_let*:
(my_let* ((a 2)
(b 3)
(c (+ a b)))
(+ a b c))
and the return value of this code should be 10. just as if it was use let*.
the code above will be expanded in my_let* to the following:
(let ()
(define a 2)
(define b 3)
(define c (+ a b))
(+ a b c))
I'm new to using macro, though i successfully written some macros, this one got me lost.
Thank you in advance.
Use syntax-parse. At the least don't even consider using defmacro in Racket.
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (my-let* stx)
(syntax-parse stx
[(_my-let* ([name:id e:expr] ...) body ...)
#'(let ()
(define name e) ...
body ...)]))
The name:id means that name must be an identifier and e:expr means
that e must an expression. These simple annotations help syntax-parse
to give you better error messages.
Example:
(my-let* ((4 2)
(b 3)
(c (+ a b)))
(+ a b c))
Here the DrRacket will color the 4 read and give the message:
my-let*: expected identifier in: 4
The Scheme way is using syntax-rules
(define-syntax my-let*
(syntax-rules ()
((_ ((binding expression) ...) body ...)
(let ()
(define binding expression) ...
body ...))))
Using defmacro is more like making a procedure.
(define (my-let-fun* bindings . body)
...)
How it should work is like this:
(my-let-fun* '((a 1) (b 2) (c (+ a b))) "test" '(list a b c))
; ==> (let () (define a 1) (define b 2) (define c (+ a b)) "test" (list a b c))
If you have not called my-let-fun* in your implementation it's just changing it to a defmacro and you're done.
(defmacro my-let* (bindings . body)
...)
It's quite simple to do either with a helper to do recursion or foldr to do the bindings. Good luck!
Your my-let* will only work in #lang racket and perhaps #!r6rs and later. In R5RS you will get an error in this case:
(my-let* ((a 1) (b 2) (c (+ a b)))
(list a b c))
; signals an error that a is undefined.
The reason is that it expands to something like this:
(let ((a 'undefined) (b 'undefined) (c 'undefined))
(let ((tmp1 1) (tmp2 2) (tmp3 (+ a b)))
(set! a tmp1)
(set! b tmp2)
(set! c tmp3))
(list a b c))
Between the error messages and some judicious use of the macro stepper I think it's hard to go too wrong here. The trouble is just making sure you've put things together right using either conses or unquote-splicing. I believe the standard practice in such macros is heavy use of quasiquote and unquote-splicing in order for the output to as closely match the intended statement as possible, otherwise the macro can become quite inscrutable. But I am not a defmacro expert.
#lang racket/base
(require (for-syntax racket/base)
compatibility/defmacro)
(defmacro my-let* (binding-pairs . body)
(define defines (map (lambda (bp) (cons 'define bp)) binding-pairs))
`(let ()
,#defines
,#body))
(my-let* ((a 2)
(b (expt a 3)))
(printf "a:~a\nb:~a\n" a b)
(+ a b))
As an exercise in learning the Racket macro system, I've been implementing a unit testing framework, based on the C++ catch framework. One of the features of that framework is that if I write a check like this:
CHECK(x == y); // (check x y)
When the check is violated the error message will print out the values of x and y, even though the macro used is completely generic, unlike other test frameworks that require you to use macros like CHECK_EQUALS, CHECK_GREATER, etc. This is possible through some hackery involving expression templates and operator overloading.
It occurs to me that in Racket you should be able to do an even better job. In the C++ version the macro can't see inside subexpressions, so if you write something like:
CHECK(f(x, g(y)) == z); // (check (= (f x (g y)) z))
When the check is violated you only find out the values of the left and right hand side of the equal sign, and not the values of x, y, or g(y). In racket I expect it should be possible to recurse into subexpressions and print a tree showing each step of the evaluation.
Problem is I have no idea what the best way to do this is:
I've gotten fairly familiar with syntax-parse, but this seems beyond its abilities.
I read about customizing #%app which almost seems like what I want, but if for example f is a macro, I don't want to print out every evaluation of the expressions that are in the expansion, just the evaluations of the expressions that were visible when the user invoked the check macro. Also not sure if I can use it without defining a language.
I could use syntax-parameterize to hijack the meaning of the basic operators but that won't help with function calls like g(y).
I could use syntax->datum and manually walk the AST, calling eval on subexpressions myself. This seems tricky.
The trace library almost looks like what it does what I want, but you have to give it a list of functions upfront, and it doesn't appear to give you any control over where the output goes (I only want to print anything if the check fails, not if it succeeds, so I need to save the intermediate values to the side as execution proceeds).
What would be the best or at least idiomatic way to implement this?
Here is something to get you started.
#lang racket
(require (for-syntax syntax/parse racket/list))
(begin-for-syntax
(define (expression->subexpressions stx)
(define expansion (local-expand stx 'expression '()))
(syntax-parse expansion
#:datum-literals (#%app quote)
[x:id (list #'x)]
[b:boolean (list #'b)]
[n:number (list #'n)]
; insert other atoms here
[(quote literal) (list #'literal)]
[(#%app e ...)
(cons stx
(append-map expression->subexpressions (syntax->list #'(e ...))))]
; other forms in fully expanded syntax goes here
[else
(raise-syntax-error 'expression->subexpressions
"implement this construct"
stx)])))
(define-syntax (echo-and-eval stx)
(syntax-parse stx
[(_ expr)
#'(begin
(display "] ") (displayln (syntax->datum #'expr))
(displayln expr))]))
(define-syntax (echo-and-eval-subexpressions stx)
(syntax-parse stx
[(_ expr)
(define subs (expression->subexpressions #'expr))
(with-syntax ([(sub ...) subs])
#'(begin
; sub expressions
(echo-and-eval sub)
...
; original expression
(echo-and-eval expr)))]))
(echo-and-eval-subexpressions (+ 1 2 (* 4 5)))
The output:
] (+ 1 2 (* 4 5))
23
] +
#<procedure:+>
] 1
1
] 2
2
] (#%app * '4 '5)
20
] *
#<procedure:*>
] 4
4
] 5
5
] (+ 1 2 (* 4 5))
23
An alternative to printing everything is to add a marker for stuff that should be shown. Here's a rough simple sketch:
#lang racket
(require racket/stxparam)
(define-syntax-parameter ?
(λ(stx) (raise-syntax-error '? "can only be used in a `test' context")))
(define-syntax-rule (test expr)
(let ([log '()])
(define (log! stuff) (set! log (cons stuff log)))
(syntax-parameterize ([? (syntax-rules ()
[(_ E) (let ([r E]) (log! `(E => ,r)) r)])])
(unless expr
(printf "Test failure: ~s\n" 'expr)
(for ([l (in-list (reverse log))])
(for-each display
`(" " ,#(add-between (map ~s l) " ") "\n")))))))
(define x 11)
(define y 22)
(test (equal? (? (* (? x) 2)) (? y)))
(test (equal? (? (* (? x) 3)) (? y)))
which results in this output:
Test failure: (equal? (? (* (? x) 3)) (? y))
x => 11
(* (? x) 3) => 33
y => 22
I frequently use Racket's pattern-matching construct match, and I thought a way to help myself with debugging programs using match, and to learn how Racket/Scheme macros work, would be to create a macro that includes information like which pattern was matched.
In other words, I'm looking to create a macro that, given this:
(match/debug 'two
['one 1]
['two 2])
Outputs something like this:
Case 2 <-- Printed
2 <-- Returned value
The main obstacle so far has been trying to get the numbers signifying the resolved case to show up correctly.
My target was to try to write something that would expand like this:
(match 'two
['one (displayln "Case 1") 1]
['two (displayln "Case 2") 2])
But I haven't been able to figure out any way to generate those "Case #" strings.
Here is my attempted macro definition:
(define-syntax-rule (match/debug id [pattern value] ...)
(let ([index 0])
(match id
[(begin
(set! index (add1 index))
pattern)
(printf "Case ~a\n" index)
value] ...)))
It appears as though the syntax of match won't let me do something like this, but this was the only way I could think of. I'm only really used to Common Lisp's style of macros.
Here is a solution.
The helper function clauses->numbers returns a list of the numbers from 0 to the one less than the number of clauses. This is then used to give each clause its own number. Note that this solution counts from 0 (and not 1 as in your examples).
#lang racket
(require (for-syntax syntax/parse))
(begin-for-syntax
(require racket/list) ; import range
(define (clauses->numbers stx)
(range (length (syntax->list stx)))))
(define-syntax (match/debug stx)
(syntax-parse stx
[(_match/debug id [pattern value] ...)
(with-syntax ([(n ...) (clauses->numbers #'([pattern value] ...))])
(syntax/loc stx
(match id
[pattern (begin (displayln (~a "Case: " n)) value)]
...)))]))
(match/debug 'one
['one 1]
['two 2])
(match/debug 'two
['one 1]
['two 2])
The output:
Case: 0
1
Case: 1
2
Is there any way to detect if a macro is expanding inside a pattern match?
Here's an example macro that I'd like to write, but it fails inside a match-define:
#lang racket/base
(require racket/match (for-syntax racket/base syntax/parse))
(struct point (x y))
(define-syntax (friendly-point stx)
(syntax-parse stx
[(_ arg* ...)
#'(begin (printf "Now making a point\n") (point arg* ...))]
[_ #'(begin (printf "Hello point\n") point)]))
(define p (friendly-point 1 2))
;; Prints "Now making a point"
(match-define (friendly-point x y) p)
;; ERROR
Yes. Instead of using an ordinary syntax transformer created with define-syntax, use define-match-expander to create a macro that can cooperate with match.
(require (for-syntax syntax/parse))
(define-match-expander positive
(syntax-parser
[(_ n)
#'(? positive? n)]))
(match 3
[(positive n) (~a n " is positive")])
; => "3 is positive"
The define-match-expander form is flexible: it can be used to create macros that may only be used inside of match, but it can also be used to create macros that expand differently depending on how they are used by providing two transformer functions, one for each context. This allows you to have “context-sensitive” identifiers which work as both functions and as match expanders.
(require (for-syntax syntax/parse)
(prefix-in base: racket/base))
(define-match-expander syntax
(syntax-parser
[(_ x)
#'(? syntax? (app syntax->datum x))])
(make-rename-transformer #'base:syntax))
(match (syntax (1 2 3))
[(syntax n) (~a n " is a syntax list")])
If you need even more flexibility, you can forego define-match-expander entirely and define a custom struct with the prop:match-expander structure type property. This can be combined with prop:procedure to achieve the two-argument functionality described above, but it can also hold state, and it can be paired with other structure type properties such as prop:rename-transformer to allow the same identifier to function in many, many different contexts.
What you are looking for is define-match-expander. It allows you to make a macro that is expanded inside of a pattern matching context. (Also, because it takes in two thunks, you can have a variant that is also used when not in a matching context. Next, I should point out that
Next, you can have a printing side effect inside of the template of a define-match-expander, but you can have in the macro itself. (Note though that the side effect will not occur if your module has already been expanded. This is explain in more detail in this paper.
So, using match expanders, including a second function for use outside of match, you get the following code:
#lang racket/base
(require racket/match (for-syntax racket/base syntax/parse))
(struct point (x y))
(define-match-expander friendly-point
(lambda (stx)
(syntax-parse stx
[(_ arg* ...)
(printf "Now matching a point\n")
#'(point arg* ...)]
[_ #'point]))
(lambda (stx)
(syntax-parse stx
[(_ args* ...)
#'(begin (printf "Now making a point\n") (point args* ...))])))
(define p (friendly-point 1 2))
;; Prints "Now making a point"
(match-define (friendly-point x y) p)
;; Works fine now