Skip to content

Support function prefixes to avoid namespace collisions #8

@cinova

Description

@cinova

In the Recurly LFE client, we've had to create a modified version of the defelem macro in order to not have unexpected collisions with function names. So when we use Exemplar to create XML tags, for a Recurly account, we're not stomping on a function called (account ...) (and we're not asking a user of the rcrly library to do that). We do this via a "prefix" that is pre-pended to the XML-generating functions, but which is not reflected in the XML output:

Here's the macro we created:

(defmacro defelem arg
  "This is a custom defelem macro based on the one in Examplar here:
     * https://github.com/lfex/exemplar/blob/master/include/macros.lfe
  The macro below differs in that is expects a prefix when defining the element
  and then when calling it -- something designeed to avoid namespace collisions
  with the relatively general names of the XML elements defined by the Recurly
  API."
  (let* ((prefix-and-tag (atom_to_list (car arg)))
         (`(,prefix ,tag) (string:tokens prefix-and-tag "/")))
    `(progn
      (defun ,(list_to_atom (++ prefix "/" tag)) ()
        (exemplar-xml:make-xml ,tag))
      (defun ,(list_to_atom (++ prefix "/" tag)) (content)
        (exemplar-xml:make-xml ,tag content))
      (defun ,(list_to_atom (++ prefix "/" tag)) (attrs content)
        (exemplar-xml:make-xml ,tag attrs content)))))

Here are some definitions:

;; top-level XML tags
(defelem xml/account)

;; child tags
(defelem xml/username)
(defelem xml/email)
(defelem xml/first_name)
(defelem xml/last_name)
(defelem xml/company_name)
(defelem xml/vat_number)
(defelem xml/tax_exempt)
(defelem xml/entity_use_code)
(defelem xml/billing_info)
(defelem xml/address)
(defelem xml/accept_language)

These allow the following usage:

> (slurp "src/rcrly-xml.lfe")
#(ok rcrly-xml)
> (xml/account (xml/company_name "Bob's Red Mill"))
"<account><company_name>Bob's Red Mill</company_name></account>"

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions