从FORMAT输出到字符串?

the*_*bda 2 database common-lisp string-formatting

就在最近我一直在玩lisp,我正在尝试创建一个通用的本地数据库,我正在关注另一个涵盖大多数此类项目的教程,但是我决定要添加一个"简单" "功能.

我正在尝试以自定义格式生成时间戳,并将它们保存为字符串.我正在尝试将格式生成的字符串存储到使用defvar声明的变量中,方法是将变量作为第一个参数调用format,但不是保存完整输出,而是获取月份的日期.这是我的代码:

(defun date ()

    (setq *SUPPRESS-SIMILAR-CONSTANT-REDEFINITION-WARNING* 1)
    (defconstant *day-names*
    '("Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"))
    *DAY-NAMES*

    (multiple-value-bind
        (second minute hour date month year day-of-week dst-p tz)
        (get-decoded-time)
    (defvar datetime)   
    (format datetime "~2,'0d:~2,'0d:~2,'0d ~a ~d/~2,'0d/~d (GMT~@d)"
    hour
    minute
    second
    (nth day-of-week *day-names*)
    month
    date
    year
    (- tz)
    (return-from date datetime))))

(defun make-entry (category subject idea info researched)
    (defvar date (date))
    (list :category category :subject subject :date date :idea idea :info info :researched researched))
Run Code Online (Sandbox Code Playgroud)

的期望值日期补充条目应类似于二十一点28分十八秒周三2014年7月30日(GMT-7) ,但我最终只有30,而不是它的其余部分.此外,我已经测试找到返回的30的类型,它确实是一个整数,而不是char-stream(字符串)应该是.因此,我确信这与格式中的"~d"有关,但我可能错了.真的,我只是想将系统时间的格式化版本传递给make-entry.

Ina*_*thi 5

那好吧.[Dons代码审查帽子]


首先,让我们更加一致地缩进.你确实做了比典型的lisp-newbie在缩进时做得更好的事情,但是把大部分内容冲到了一列.缩进级别可以为您提供有关程序控制流程的大量提示.一旦你习惯了,我的意思是.

(defun date ()

  (setq *SUPPRESS-SIMILAR-CONSTANT-REDEFINITION-WARNING* 1)
  (defconstant *day-names*
    '("Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"))
  *DAY-NAMES*

  (multiple-value-bind
        (second minute hour date month year day-of-week dst-p tz)
      (get-decoded-time)
    (defvar datetime)   
    (format datetime "~2,'0d:~2,'0d:~2,'0d ~a ~d/~2,'0d/~d (GMT~@d)"
            hour minute second
            (nth day-of-week *day-names*)
            month date year
            (- tz)
            (return-from date datetime))))

(defun make-entry (category subject idea info researched)
  (defvar date (date))
  (list :category category :subject subject :date date :idea idea :info info :researched researched))
Run Code Online (Sandbox Code Playgroud)

可以,但不应该使用defconstantdefvar本地.要么制作那些顶级表单,要么使用它们使它们成为本地定义let.在你的情况下,constant作为一个全局有意义,而var应该是一个局部变量(但稍后更多).此外,既然您没有在每个函数调用上重新定义常量,则不需要压制该重定义警告.

(defconstant *day-names* '("Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"))

(defun date ()
  *DAY-NAMES*

  (multiple-value-bind
        (second minute hour date month year day-of-week dst-p tz)
      (get-decoded-time)
    (let ((datetime))
      (format datetime "~2,'0d:~2,'0d:~2,'0d ~a ~d/~2,'0d/~d (GMT~@d)"
              hour minute second
              (nth day-of-week *day-names*)
              month date year
              (- tz)
              (return-from date datetime)))))
Run Code Online (Sandbox Code Playgroud)

Lisp表单自动返回它计算的最后一个值,但任何早期的表单只会产生副作用而不是值.*DAY-NAMES*一开始没什么特别的date.此外,由于你似乎试图返回datetimedate,你不需要调用return-from.相反,只是评估datetime.

(defun date ()
  (multiple-value-bind
        (second minute hour date month year day-of-week dst-p tz)
      (get-decoded-time)
    (let ((datetime))
      (format datetime "~2,'0d:~2,'0d:~2,'0d ~a ~d/~2,'0d/~d (GMT~@d)"
              hour minute second
              (nth day-of-week *day-names*) 
              month date year
              (- tz))
      datetime)))
Run Code Online (Sandbox Code Playgroud)

format将流作为其第一个参数.而变量不是流(虽然它可能包含一个;你的不包含).你似乎想要做的是将当前时间作为字符串返回,根据你的format指令格式化.要做到这一点,你根本不需要中间值.只需NIL作为第一个参数传递format,它将自动创建一个包含内容的新字符串,然后返回它.

(defun date ()
  (multiple-value-bind
        (second minute hour date month year day-of-week dst-p tz)
      (get-decoded-time)
    (format nil "~2,'0d:~2,'0d:~2,'0d ~a ~d/~2,'0d/~d (GMT~@d)"
            hour minute second
            (nth day-of-week *day-names*) 
            month date year
            (- tz))))
Run Code Online (Sandbox Code Playgroud)

在这一点上,date似乎做了一些有意义的事情.

cl-user> (date)
"15:39:12 Thursday 7/31/2014 (GMT-5)"
cl-user> 
Run Code Online (Sandbox Code Playgroud)

因为你只是试图把一些值的列表,你也不需要创建一个局部变量来保存的结果(date)make-entry.

(defun make-entry (category subject idea info researched)
  (list :category category :subject subject :date (date) :idea idea :info info :researched researched))
Run Code Online (Sandbox Code Playgroud)

此时,make-entry返回plist:DATE值为适当格式化字符串的a date.

cl-user> (make-entry "something" "something else" "blah" "bleeh" "stop using side effects")
(:CATEGORY "something" :SUBJECT "something else" :DATE
 "15:41:57 Thursday 7/31/2014 (GMT-5)" :IDEA "blah" :INFO "bleeh" :RESEARCHED
 "stop using side effects")
cl-user> 
Run Code Online (Sandbox Code Playgroud)
(defconstant *day-names* '("Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"))

(defun date ()
  (multiple-value-bind
        (second minute hour date month year day-of-week dst-p tz)
      (get-decoded-time)
    (format nil "~2,'0d:~2,'0d:~2,'0d ~a ~d/~2,'0d/~d (GMT~@d)"
            hour minute second
            (nth day-of-week *day-names*) 
            month date year
            (- tz))))

(defun make-entry (category subject idea info researched)
  (list :category category :subject subject :date (date) :idea idea :info info :researched researched))
Run Code Online (Sandbox Code Playgroud)

如果您正在关注PCL数据库章节,请记住,在您阅读数据库时,需要再次解码以这种方式格式化的日期,假设您计划执行除字符串比较之外的任何其他操作用它.因此,根据您的具体用例,实际存储原始输出可能更有意义(get-universal-time).