[racket-users] Macro guards question
Hi Guys, What are the rules for macro guards? I’ve only seen examples with (identifier? #’val) being used. What about (number? #’val) or (spring? #’val)? When I try these I get a foo: bad syntax so I’m suspecting these can’t be used or there’s some trick to them. What I’ve been trying to create (and maybe this isn’t the right way to go about it) is a syntax-case that would have have various type checks as guards and then select the branch based on whether I’ve got an identifier or just a symbol, or a number or a string, etc. (syntax-case six () [(_ arg) (identifier? #’arg) #’(identifier-handler arg)] [(_ arg) (symbol? #’arg) #’(symbol-handler arg)] [(_ arg) (string? #’arg) #’(string-handler arg)] …) That sort of thing. Primarily I find myself running into an issue where I’m using symbols for lookup keys and identifiers for their reference values and running into a wall of wanting the macro to go ahead and handle them differently without have the old “foo undefined” popping up. :) Kevin -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/DED7E28E-9B3D-4045-B0DC-CBD3AB11E653%40gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Macro guards question
#'arg is a syntax object, therefore (number? #'arg) or (string? #'arg) will always be false. If you are trying to dispatch based on literals, you could use e.g. (number? (syntax-e #'arg)) to identify a numeric literal. But it is not very common that a macro handles a numeric literal differently than an identifier that is bound to a numeric value at runtime. I'm guessing you can use a regular procedure and cond for most of this. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/111c1509-d77f-48d6-8c1f-19a37748cace%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Macro guards question
The issue is that #'arg will always be a syntax object. An identifier is a kind of syntax object, so it makes sense to test (identifier? #’arg). However, (symbol? #’arg) and (string? #’arg) will always fail. Suppose then that you invoke the macro with "1" as the operand, it would fail every case in syntax-case, so syntax-case throws a bad syntax (because a syntax transformation must be total), causing the error that you saw. If you insist on using syntax-case, then try this: (define-syntax (foo stx) (syntax-case stx () [(_ arg) (identifier? #'arg) #'1] [(_ arg) (string? (syntax->datum #'arg)) #'2] [(_ arg) (number? (syntax->datum #'arg)) #'3] [(_ (quote* x)) (and (free-identifier=? #'quote* #'quote) (symbol? (syntax->datum #'x))) #'4] [(_ _) #'5])) (foo a) ;=> 1 (foo "a") ;=> 2 (foo 10) ;=> 3 (foo 'a) ;=> 4 (foo (bar x)) ;=> 5 A better way though is to use syntax-parse. (require (for-syntax syntax/parse)) (define-syntax (foo stx) (syntax-parse stx #:literals (quote) [(_ arg:id) #'1] [(_ arg:string) #'2] [(_ arg:number) #'3] [(_ (quote x:id)) #'4] [(_ _) #'5])) (foo a) ;=> 1 (foo "a") ;=> 2 (foo 10) ;=> 3 (foo 'a) ;=> 4 (foo (bar x)) ;=> 5 On Wed, May 29, 2019 at 10:23 AM Kevin Forchione wrote: > Hi Guys, > What are the rules for macro guards? I’ve only seen examples with > (identifier? #’val) being used. What about (number? #’val) or (spring? > #’val)? When I try these I get a foo: bad syntax so I’m suspecting these > can’t be used or there’s some trick to them. > > What I’ve been trying to create (and maybe this isn’t the right way to go > about it) is a syntax-case that would have have various type checks as > guards and then select the branch based on whether I’ve got an identifier > or just a symbol, or a number or a string, etc. > > (syntax-case six () > [(_ arg) (identifier? #’arg) #’(identifier-handler arg)] > [(_ arg) (symbol? #’arg) #’(symbol-handler arg)] > [(_ arg) (string? #’arg) #’(string-handler arg)] >…) > > That sort of thing. > > Primarily I find myself running into an issue where I’m using symbols for > lookup keys and identifiers for their reference values and running into a > wall of wanting the macro to go ahead and handle them differently without > have the old “foo undefined” popping up. :) > > Kevin > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/racket-users/DED7E28E-9B3D-4045-B0DC-CBD3AB11E653%40gmail.com > . > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CADcuegvP%3DpmJRuZCSFmQjtyo7nxQFmo0JnoXjCW1WpnEdmnMpg%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
Re: [racket-users] Macro guards question
> On May 29, 2019, at 11:09 AM, Sorawee Porncharoenwase > wrote: > > (foo a) ;=> 1 > (foo "a") ;=> 2 > (foo 10) ;=> 3 > (foo 'a) ;=> 4 > (foo (bar x)) ;=> 5 Ah… thanks so much for the explanation. That’s put me much closer (I hope!) to the solution I’m after. A bit of stumbling around through some documentation has got me this far.Being able to handle (foo a) and (foo b) below differently is a distinction I’ve been after for a while! #lang racket (define-syntax (foo stx) (syntax-case stx () [(_ arg) (and (identifier? #'arg) (identifier-binding #'arg 0 #t)) #'1] [(_ arg) (identifier? #'arg) #'2] [(_ arg) (string? (syntax->datum #'arg)) #'3] [(_ arg) (number? (syntax->datum #'arg)) #'4] [(_ (quote* x)) (and (free-identifier=? #'quote* #'quote) (symbol? (syntax->datum #'x))) #'5] [(_ _) #'6])) (define a #t) ;=> a is top-level bound, b is not. (foo a) ;=> 1 (foo b) ;=> 2 (foo "a") ;=> 3 (foo 10) ;=> 4 (foo 'a) ;=> 5 (foo (bar x)) ;=> 6 Kevin -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/506321EF-0D5B-4551-8671-268E6808B015%40gmail.com. For more options, visit https://groups.google.com/d/optout.