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