lisp: named parameters for structured data - lisp to xml conversion

Posted on 2005-03-14
Medium Priority
Last Modified: 2013-11-19
Here's my simple LISP program for converting structured data to XML:

(defun strcat (&rest args)
  (apply #'concatenate
    (cons 'string args)))

(defun rectangle (x y width height color &rest children)
      " x='" (princ-to-string x) "'"
      " y='" (princ-to-string y) "'"
      " width='" (princ-to-string width) "'"
      " height='" (princ-to-string height) "'"
      " color='" (princ-to-string color) "'"
    (apply #'strcat children)

  (rectangle 0 0 10 20 "blue"
    (rectangle 1 1 3 4 "green")
    (rectangle 5 1 3 4 "red")

Here's the output:

"<rectangle x='0' y='0' width='10' height='20' color='blue'><rectangle x='1' y='1' width='3' height='4' color='green'></rectangle><rectangle x='5' y='1' width='3' height='4' color='red'></rectangle></rectangle>"

However, I'd rather want the LISP program to use named parameters like this:

  (rectangle x: 0 y: 0 width: 10 height: 20 color: "blue"
    (rectangle x: 1 y: 1 width: 3 height: 4 color: "green")
    (rectangle x: 5 y: 1 width: 3 height: 4 color: "red")

Sort-of like as described on

  (button label: "Back"
          image: left-arrow
          oncommand: back-command)
  (button label: "Next"
          image: right-arrow
          oncommand: next-command))

I've tried using "&key" in common lisp, but using it seems to require that all (not some) parameters be named.  Example:

  (defun foo (&rest rest &key a b c) (list rest a b c))
  (print (foo :a 1 :b 2 :c 3 1 2 3))

output error:

  *** - FOO: keyword arguments in (:A 1 :B 2 :C 3 1 2 3) should occur pairwise

I can do this:

  (defun foo (&rest rest) (list rest))
  (print (foo :a 1 :b 2 :c 3 1 2 3))

But, how does one bind and use the named parameters as in the original program.  Is there a convention for this?  Am I even on the right track?

Also, what is the difference between ":x" and "x:"?  The latter "looks" better in my code (the colon separates the attribute key and value), but the former seems more standard.
Question by:ext2
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2

Author Comment

ID: 13541965
What I need is much like this:

LAML: Lisp Abstracted Markup Language

Author Comment

ID: 13552353
[[Request for refund of points]]

I think I've figured this all out.  The essential idea was to just use &rest (and not use &key) as such:

  (defun foo (&rest lst)
    (list "foo" (atts lst) (elements lst))

and then write one's own code to extract the attributes and elements from lst:

;; extract attributes from list
(defun atts (lst)
    ((null  (first  lst)) '())  ;; done
    ((listp (first  lst)) (atts (rest lst)))  ;; found element (ignore)
    ((null  (second lst)) nil) ;; error
    ((and (atom (first  lst))  ;; found attribute
          (atom (second lst)))
            (cons (list (first lst) (second lst))
                  (atts (rest (rest lst)))
    (t nil) ;; error

;; extract elements from list
(defun elements (lst)
    ((null  (first lst)) '()) ;; done
    ((listp (first lst)) (cons (first lst) (elements (rest lst)))) ;; found element
    (t (elements (rest (rest lst)))) ;; found attribute or error (ignore)

One can follow the same design as in LAML of generating the abstract syntax tree (AST) and then serializing it as XML.

Accepted Solution

EE_AutoDeleter earned 0 total points
ID: 14877717
Because you have presented a solution to your own problem which may be helpful to future searches, this question is now PAQed and your points have been refunded.


Featured Post

7 Extremely Useful Linux Commands for Beginners

Just getting started with Linux? Here's a quick start guide that has 7 commands that we believe will come in handy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question