Re: [racket-users] Re: Macro containing a list of elements that each have optional keyword options

2019-08-19 Thread Brian Adkins
On Monday, August 19, 2019 at 5:48:29 PM UTC-4, Sorawee Porncharoenwase 
wrote:
>
> You could use (splicing) syntax class to help with normalization:
>
> #lang racket
>
> (require syntax/parse/define
>  (for-syntax syntax/parse
>  racket/syntax))
>
> (begin-for-syntax
>   (define-splicing-syntax-class methods-cls
> #:attributes (methods)
> (pattern (~seq #:methods (method:expr ...))
>  #:with methods #'(list 'method ...))
> (pattern (~seq #:method method:expr)
>  #:with methods #'(list 'method)))
>
>   (define-syntax-class route-cls
> (pattern (route:string
>   handler:id
>   (~alt (~optional ms:methods-cls
>#:name "#:method, or #:methods option")
> (~optional (~seq #:when guard-e:expr)
>#:name "#:when option")) ...)
>  #:with methods #`#,(or (attribute ms.methods) #'(list))
>  #:with guard #`#,(attribute guard-e
>
> (define-simple-macro (routes :route-cls ...)
>   #:with name (format-id this-syntax "axio-routes")
>   (define name (list (list route handler methods guard) ...)))
>
> (define (foo-handler) 0)
> (define (bar-handler) 0)
> (define (baz-handler) 0)
> (define (use-bar-handler?) 0)
>
> (routes
>  ("/foo" foo-handler #:method put)
>  ("/bar" bar-handler #:methods (put update) #:when use-bar-handler?)
>  ("/baz" baz-handler))
>
> axio-routes
>
>
Thanks your idea cleans it up nicely!  I've broken up the code into 4 file 
and placed them in a gist:

https://gist.github.com/lojic/842619ab2c59a2c96960f9ccd30bc136

I'm not thrilled with the fact that the routes macro has to export the 
axio-routes binding. I expect there is a better way to communicate between 
the routes macro and find-route function.

I'll add interpolation to the URL paths next e.g.  (route "/user/~id" ...) 

-- 
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/f7238c4b-6d4c-431c-a305-c4d2d7bdbfb5%40googlegroups.com.


Re: [racket-users] Re: Macro containing a list of elements that each have optional keyword options

2019-08-19 Thread Sorawee Porncharoenwase
You could use (splicing) syntax class to help with normalization:

#lang racket

(require syntax/parse/define
 (for-syntax syntax/parse
 racket/syntax))

(begin-for-syntax
  (define-splicing-syntax-class methods-cls
#:attributes (methods)
(pattern (~seq #:methods (method:expr ...))
 #:with methods #'(list 'method ...))
(pattern (~seq #:method method:expr)
 #:with methods #'(list 'method)))

  (define-syntax-class route-cls
(pattern (route:string
  handler:id
  (~alt (~optional ms:methods-cls
   #:name "#:method, or #:methods option")
(~optional (~seq #:when guard-e:expr)
   #:name "#:when option")) ...)
 #:with methods #`#,(or (attribute ms.methods) #'(list))
 #:with guard #`#,(attribute guard-e

(define-simple-macro (routes :route-cls ...)
  #:with name (format-id this-syntax "axio-routes")
  (define name (list (list route handler methods guard) ...)))

(define (foo-handler) 0)
(define (bar-handler) 0)
(define (baz-handler) 0)
(define (use-bar-handler?) 0)

(routes
 ("/foo" foo-handler #:method put)
 ("/bar" bar-handler #:methods (put update) #:when use-bar-handler?)
 ("/baz" baz-handler))

axio-routes


On Mon, Aug 19, 2019 at 1:56 PM Brian Adkins  wrote:

> (define-syntax (routes stx)
>   (syntax-parse stx
> [ (routes (element ...) ...)
>   (with-syntax ([ name  (format-id stx "axio-routes") ])
> #'(define name (list (route-element element ...) ...)))]))
>
> (define-syntax (route-element stx)
>   (syntax-parse stx
> [ (route-element route:string
>  handler:id
>  (~alt (~optional (~or* (~seq #:methods (methods:expr
> ...))
> (~seq #:method method:expr))
>   #:name "#:method, or #:methods
> option")
>(~optional (~seq #:when guard:expr)
>   #:name "#:when option"))
>  ...)
>   (with-syntax ([ method-list (let ([ m  (attribute method)  ]
> [ ms (attribute methods) ])
> (cond [ m(list m) ]
>   [ ms   ms   ]
>   [ else '()  ]))]
> [ guard-func (let ([ fun (attribute guard) ])
>(if fun
>fun
>#f)) ])
> #'(list route handler 'method-list guard-func))]))
>
> (routes
>  ("/foo" foo-handler #:method put)
>  ("/bar" bar-handler #:methods (put update) #:when use-bar-handler?)
>  ("/baz" baz-handler))
>
> axio-routes
>
> ==>  '(("/foo" # (put) #f) ("/bar"
> # (put update) #)
> ("/baz" # () #f))
>
> I know it ain't pretty yet, but it works now, so I can enhance it later. I
> should probably use a struct for each route vs. a list.
>
> --
> 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/ffc7ec25-f663-4d1d-a3d6-d3097d9c3963%40googlegroups.com
> 
> .
>

-- 
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/CADcuegsvZ21nJTcpFzMRU0fTjyXtbUY-ZoDDT9A%2BN5qJHnFsxg%40mail.gmail.com.


[racket-users] Re: Macro containing a list of elements that each have optional keyword options

2019-08-19 Thread Brian Adkins
(define-syntax (routes stx)
  (syntax-parse stx
[ (routes (element ...) ...)
  (with-syntax ([ name  (format-id stx "axio-routes") ])
#'(define name (list (route-element element ...) ...)))]))

(define-syntax (route-element stx)
  (syntax-parse stx
[ (route-element route:string
 handler:id
 (~alt (~optional (~or* (~seq #:methods (methods:expr 
...))
(~seq #:method method:expr))
  #:name "#:method, or #:methods 
option")
   (~optional (~seq #:when guard:expr)
  #:name "#:when option"))
 ...)
  (with-syntax ([ method-list (let ([ m  (attribute method)  ]
[ ms (attribute methods) ])
(cond [ m(list m) ]
  [ ms   ms   ]
  [ else '()  ]))]
[ guard-func (let ([ fun (attribute guard) ])
   (if fun
   fun
   #f)) ])
#'(list route handler 'method-list guard-func))]))

(routes
 ("/foo" foo-handler #:method put)
 ("/bar" bar-handler #:methods (put update) #:when use-bar-handler?)
 ("/baz" baz-handler))

axio-routes

==>  '(("/foo" # (put) #f) ("/bar" 
# (put update) #) 
("/baz" # () #f))

I know it ain't pretty yet, but it works now, so I can enhance it later. I 
should probably use a struct for each route vs. a list.

-- 
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/ffc7ec25-f663-4d1d-a3d6-d3097d9c3963%40googlegroups.com.


[racket-users] Re: Macro containing a list of elements that each have optional keyword options

2019-08-19 Thread Brian Adkins
On Monday, August 19, 2019 at 3:35:00 PM UTC-4, Brian Adkins wrote:
>
> I'm working on a macro to allow the following:
>
> (routes
>  ("/foo" foo-handler #:method put)
>  ("/bar" bar-handler #:methods (put update))
>  ("/baz" baz-handler))
>
> The idea is that you could restrict a route based on the HTTP method 
> either for one method using #:method or for a list of methods using 
> #:methods. I tried using some ideas from the following examples:
>
> https://docs.racket-lang.org/syntax/Optional_Keyword_Arguments.html
>
> https://docs.racket-lang.org/syntax/More_Keyword_Arguments.html
>
> The attempt below does not work, and from my debugging I think it's 
> probably the wrong approach. If there are examples of this sort of thing, 
> I'd love to see them.
>
> Thanks,
> Brian Adkins
>
> (define-syntax (routes stx)
>   (syntax-parse stx
> [ (routes (route:string
>handler:id
>(~alt (~optional (~or* (~seq #:methods (methods:expr ...))
>   (~seq #:method method:expr))
> #:name "#:method, or #:methods option")
>  (~optional (~seq #:when guard:expr)
> #:name "#:when option"))
>...)
>   ...)
>   (with-syntax ([ name  (format-id stx "axio-routes") ])
> #'(define name (list (list route handler 'method (list 'methods 
> ...)) ...)))]))
>
>
The following got me over the main hurdle:

(define-syntax (routes stx)
  (syntax-parse stx
[ (routes (element ...) ...)
  (with-syntax ([ name  (format-id stx "axio-routes") ])
#'(define name (list (route-element element ...) ...)))]))

(define-syntax (route-element stx)
  (syntax-parse stx
[ (route-element route:string
 handler:id
 (~alt (~optional (~or* (~seq #:methods (methods:expr 
...))
(~seq #:method method:expr))
  #:name "#:method, or #:methods 
option")
   (~optional (~seq #:when guard:expr)
  #:name "#:when option"))
 ...)
  (with-syntax ([ m  (or (attribute method)  #'#f) ]
[ ms (or (attribute methods) #'#f) ])
#'(list route handler 'm 'ms))]))

(routes
 ("/foo" foo-handler #:method put)
 ("/bar" bar-handler #:methods (put update))
 ("/baz" baz-handler))

axio-routes

==> '(("/foo" # put #f) ("/bar" 
# #f (put update)) ("/baz" # 
#f #f))

Now I just need to normalize to a list of HTTP methods vs. having separate 
fields. 

-- 
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/0e3bd33f-9666-4f3f-800e-1ccd7f6a2dee%40googlegroups.com.