guile-user
[Top][All Lists]
Advanced

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

Re: Write a macro which defines a procedure


From: Zelphir Kaltstahl
Subject: Re: Write a macro which defines a procedure
Date: Sat, 20 Jul 2019 19:29:45 +0200
User-agent: Posteo Webmail

Hey Ricardo,

Thanks for the advice! I did not remember, that I could use ,expand in the Guile REPL. This was I found out about an issue, but not sure how to solve it. It seems like `module-define!` wants to have a symbol as input. But I could not figure out how to create a symbol from an identifier.

Here is my updated version of the macro:

--------8<--------begin-------->8--------
(use-modules (web uri)
             (web client)
             (json)
             (ice-9 iconv))

(define-syntax variable-name->string
  (lambda (stx)
    (syntax-case stx ()
      ((_ id)
       (identifier? #'id)
       (datum->syntax #'id (symbol->string (syntax->datum #'id)))))))

(define-syntax define-api-route
  (syntax-rules ()
    [(define-api-route route http-method my-content-type)
     (module-define! (current-module)
                     ;; `route` should be `/container/json` for example.
                     #{route}#
                     (lambda* (docker-socket #:key (data #f))
                       (call-with-values
                           (lambda ()
;; Here the route needs to be given as a string to `http-get`.
                             (http-get (variable-name->string route)
                                       #:port docker-socket
                                       #:version '(1 . 1)
                                       #:keep-alive? #f
;; Why is my quasiquote not working as expected? #:headers `((host . ("localhost" . #f)) (content-type . (my-content-type (charset . "utf-8"))))
                                       #; (list (cons "localhost" #f)
(cons 'content-type (cons my-content-type (cons 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))))))]))
--------8<--------end-------->8--------

And expanding it:

--------8<--------begin-------->8--------
,expand(define-api-route
  /container/json
  'GET
  application/x-www-form-urlencoded)
$3 = (module-define!
  (current-module)
  /container/json
  (lambda* (docker-socket #:key (data #f #:data))
    (call-with-values
      (lambda ()
        (http-get
          "/container/json"
          #:port
          docker-socket
          #:version
          '(1 . 1)
          #:keep-alive?
          #f
          #:headers
          '((host "localhost" . #f)
            (content-type
              application/x-www-form-urlencoded
              (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))))))
--------8<--------end-------->8--------

So using the Guile specific #{}# (https://www.gnu.org/software/guile/manual/html_node/Symbol-Read-Syntax.html#Symbol-Read-Syntax) did not work as I thought it might.
How can I make a symbol from an identifier? In this case:

/container/json/ -> '/container/json

Are there other things I should improve in this macro?

Regards,
Zelphir


On 2019-07-20 10:46, Ricardo Wurmus wrote:
Hi,

However, when I call this macro as follows:


--------8<--------begin-------->8--------
(define-api-route /container/json 'POST
application/x-www-form-urlencoded)
--------8<--------end-------->8--------

I get the following error:

--------8<--------begin-------->8--------
;;; <stdin>:33:0: warning: possibly unbound variable `/container/json'
;;; <stdin>:33:0: warning: possibly unbound variable
`application/x-www-form-urlencoded'
<unnamed port>:33:0: In procedure module-lookup: Unbound variable:
/container/json
--------8<--------end-------->8--------

Here it might help you to see the expansion of the macro.  In the REPL
you can use

    ,expand (define-api-route /container/json 'POST
application/x-www-form-urlencoded)

to see what Scheme code the thing expands to.


--
Ricardo



reply via email to

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