将列表解构为字符串的函数

时间:2014-03-21 13:40:49

标签: lisp destructuring

我的目标是采取一个alist(alist是传递给Drakma'参数" param;但这对于这个问题并不重要)并将其序列化转换为某种形式的字符串(在本例中为HTTP参数字符串)。

所以,让我们来一览:

    (list (cons 1 2) (cons 3 4) (cons 5 6))

那么我想要的是用这样格式化的字符串结束:

    "?1=2&3=4&5=6"

到目前为止,我所做的是:

    (defvar *s* 
      (make-array 0 
              :element-type 'character 
              :adjustable t 
              :fill-pointer 0))

    ;; (serialize-params) will return a properly formatted string 
    ;; that will be used elsewhere in another function
    (defun serialize-params (params)
      (loop for (a . b) in params
         do (format *s* "~a=~a&" a b))
      (concatenate 'string "?" (trim *s*)))

    ;; Utility function to remove the last character of a string
    (defun trim (str)
      (subseq str 0 (- (length str) 1)))

这有点工作,但我真的不喜欢这个,原因如下:

  • 我不想使用特殊变量
  • 每次我运行(serialize-params (...))*s*只是附加到上一个电话

我认为要解决我的问题,我必须以某种特殊方式使用loop,并且我可能必须在我的函数中绑定一个词法变量。问题是我不知道如何将(format nil "...")的每次迭代附加到该词法变量......

免责声明:我是lisp的新手。

1 个答案:

答案 0 :(得分:1)

with-output-to-string似乎非常适合您的问题。它创建了一个可以在循环中写入的流,并返回您写的任何字符串:

(with-output-to-string (s)
   (loop with first = t
         for (a . b) in params
         if first 
           do (setq first nil)
              (princ "?" s)
         else
           do (princ "&" s)
         end
         do (format s "~a=~a" a b)))