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: Zelphir Kaltstahl
Subject: Re: syntax-case identifier name predicate in guard expression
Date: Tue, 6 Aug 2019 01:58:16 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0

Hi Mark!

Thank you for your help!

I must have been blind from moving code back and forth and the (display
...) was still from when the output of the macro was simply a symbol,
for checking whether the guard expression in the (syntax-case ...) cases
works. Also I was confused because the error message mentioned the whole
define expression, which is why I looked in the wrong place : )

I got it working now, including the more complex case of having
variables in request URLs.
(https://gitlab.com/ZelphirKaltstahl/guile-scheme-macros/blob/fccb603a92f2c2d2709e169bbdd516fcf05a6816/procedure-defining/runnable-example.scm)

Fortunately I re-read the Guile docs and read about with-syntax.
Suddenly with-syntax made a lof of sense :D

I think I am finally getting it more or less. There were quite a few
snares to overcome for me, but I think that with some trial and error I
can now get things done.

The complex case should also be moved out of the syntax-case directly
and then I can use it in the library and can finally define API routes
without much trouble (hopefully! unless I overlooked some possibility
for sending requests to the docker API), yay!

Regards,

Zelphir


On 8/5/19 8:51 PM, Mark H Weaver wrote:
> 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]