guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: syntax-case identifier name predicate in guard expression


From: Mark H Weaver
Subject: Re: syntax-case identifier name predicate in guard expression
Date: Mon, 05 Aug 2019 14:51:36 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux)

Hi Zelphir,

Zelphir Kaltstahl <address@hidden> writes:

> Hi Guile Users!
>
> I made some progress in writing a procedure defining macro for creating
> procedures which talk to an API.
>
> I now have working code, which checks the name of an identifier in a
> guard expression:
>
> ----8<----8<----8<----
> (use-modules (web uri)
>              (web client)
>              (json)
>              (ice-9 iconv)
>              (ice-9 regex))
>
>
> (define* (send-request-to-docker-socket request-url docker-socket
> my-content-type #:key (data #f))
>   (call-with-values
>       (lambda ()
>         (http-get request-url
>                   #:port docker-socket
>                   #:version '(1 . 1)
>                   #:keep-alive? #f
>                   #:headers `((host . ("localhost" . #f))
>                               (content-type . (my-content-type (charset
> . "utf-8"))))
>                   #:body (scm->json-string data)
>                   #:decode-body? #t
>                   #:streaming? #f))
>     (lambda (response response-text)
>       (let ([resp-text-as-string (bytevector->string response-text
> "utf-8")])
>         (cons response resp-text-as-string)))))
>
>
> (define-syntax define-api-route
>   (lambda (stx)
>     (define (identifier-name->string id)
>       (symbol->string (syntax->datum id)))
>
>     ;; Not needed yet.
>     ;; (define (identifier->symbol id)
>     ;;   (syntax->datum id))
>
>     (define (contains-url-template-variable? route-as-string)
>       (string-match "<[^>]+>" route-as-string))
>
>     ;; We do not need a macro to produce syntax. Instead we need to use
> a procedure to produce the
>     ;; syntax, because we want to use it while evaluating another macro.

Right.  Before, you were trying to perform the check within a procedural
macro, whose code was run when the 'define-api-route' macro was being
_defined_, which is too early.  Here you have the right idea.

>     (define make-simple-api-route-definition-syntax
>       (lambda (route http-method my-content-type route-as-string)
>         (syntax
>          (quote simple-route))))
>
>     (syntax-case stx (GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATH)
>       [(_ route GET my-content-type)
>        (contains-url-template-variable? (identifier-name->string (syntax
> route)))
>        (syntax (quote aaa))]
>       ;; an else branch basically
>       [(_ route GET my-content-type) #t
>        (syntax
>         (define* (route docker-socket #:key (data #f))
>           (call-with-values
>               (lambda ()
>                 ;; GET request because syntax GET was specified
>                 (http-get request-url
>                           #:port docker-socket
>                           #:version '(1 . 1)
>                           #:keep-alive? #f
>                           #:headers `((host . ("localhost" . #f))
>                                       (content-type . (my-content-type
> (charset . "utf-8"))))
>                           #:body (scm->json-string data)
>                           #:decode-body? #t
>                           #:streaming? #f))
>             (lambda (response response-text)
>               (let ([resp-text-as-string (bytevector->string
> response-text "utf-8")])
>                 (cons response resp-text-as-string))))))])))
>
>
> (define* (connect-to-docker-socket #:key (socket-path
> "/var/run/docker.sock"))
>   (let ([docker-sock-addr (make-socket-address AF_UNIX socket-path)]
>         [docker-sock (socket PF_UNIX SOCK_STREAM 0)])
>     (setsockopt docker-sock SOL_SOCKET SO_REUSEADDR 1)
>     (connect docker-sock docker-sock-addr)
>     docker-sock))
>
>
> (display
>  (define-api-route /containers/json GET
> "application/x-www-form-urlencoded"))
>
>
> ;; (let ([dock-sock (connect-to-docker-socket)])
> ;;   (let ([resp-and-resp-text
> ;;          (/containers/json dock-sock
> ;;                            #:data '(("all" . "true")
> ;;                                     ("filters" . (("name" . #("db"))
> ;;                                                   ("status" .
> #("running" "exited"))))))])
> ;;     (display resp-and-resp-text)
> ;;     (newline)))
>
>
> (display
>  (define-api-route /container/json GET "application/x-www-form-urlencoded"))
> ----8<----8<----8<----
>
> However, it seems, that now I have a new problem. It seems I cannot use
> a define form inside a syntax-case case!

No, that's not it.  The problem is not with the macro itself, but with
how you're attempting to use it.

The problem is simply that the macro expands into a definition, and you
are trying to use it within an expression context, where definitions are
not allowed, here:

> (display
>  (define-api-route /containers/json GET
> "application/x-www-form-urlencoded"))

This fails for the same reason that the following fails:

  (display (define foo 1))

> While it was possible to have a define form inside a syntax-rules,
> suddenly it seems impossible inside a syntax-case?

For purposes of this issue, it is irrelevant whether the macro was
defined using syntax-rules or syntax-case.

If you have a macro that expands into a definition, then you can only
use that macro in a context where definitions are allowed.

      Best,
       Mark

reply via email to

[Prev in Thread] Current Thread [Next in Thread]