格式函数循环遍历虚线alist

时间:2016-09-16 11:20:24

标签: common-lisp

我正在开发一个将alist转换为查询参数的函数。到目前为止它看起来像这样。

(defun encode-options (opts)
  "Turns an alist into url query parameters."
  (format nil "~{~{~A=~A~}~^&~}" opts))

这适用于((a b) (c d))之类的作品(导致"A=B&C=D"),但对((a . b) (c . d))等虚线列表失败。 (导致The value B is not of type LIST.

我的问题是: format虚线列表是否有可能给我预期的结果以及如何?

1 个答案:

答案 0 :(得分:6)

  

是否可以格式化虚线列表?

不,格式遍历正确的列表。

有许多可能的方法来实现您想要的。我在这里介绍其中两个。

保留控制字符串,更改数据

(defun ensure-proper-list (value)
  (typecase value
    (null nil)
    (cons (cons (car value)
                (ensure-proper-list (cdr value))))
    (t (list value))))

现在,您转换选项参数,以便所有元素都是正确的列表:

(defun encode-options (options)
  "Turns an alist into url query parameters."
  (format nil
          "~{~{~A=~A~}~^&~}"
          (mapcar #'ensure-proper-list options)))

保留数据,更改控制字符串

(defun print-alist (stream data &optional colonp atsignp)
  (declare (ignore colonp atsignp))
  (destructuring-bind (head . tail) data
    (format stream "~A=~A" head (if (consp tail) (first tail) tail))))

使用此新格式控件,按以下方式打印列表:

(defun encode-options (options)
  "Turns an alist into url query parameters."
  (format nil
          "~{~/lib:print-alist/~^&~}"
          options))

请注意,我添加了一个包前缀lib,因为没有包,print-alist会在用户包中找到(也就是COMMON-LISP-USER),在我看来很少是你的想。来自22.3.5.4 Tilde Slash: Call Function

  

通过获取与〜/ name /指令对应的函数   查找指示中具有指示名称的符号   包。如果name不包含“:”或“::”,那么整个名称   在COMMON-LISP-USER包中查找字符串。

这就是为什么我建议总是提到带有~/指令的包。