Database 从格式输出到字符串?

Database 从格式输出到字符串?,database,common-lisp,string-formatting,Database,Common Lisp,String Formatting,就在最近,我一直在使用lisp,我正在尝试创建一个通用的本地数据库,我正在学习另一个教程,它涵盖了这类项目的大部分内容,但是我决定要添加一个“简单”的特性 我试图以自定义格式生成时间戳,并将其保存为字符串。我试图将format生成的字符串存储到使用defvar声明的变量中,方法是调用format,将该变量作为第一个参数,但我没有保存完整的输出,而是只获取当月的日期。这是我的密码: (defun date () (setq *SUPPRESS-SIMILAR-CONSTANT-REDEF

就在最近,我一直在使用lisp,我正在尝试创建一个通用的本地数据库,我正在学习另一个教程,它涵盖了这类项目的大部分内容,但是我决定要添加一个“简单”的特性

我试图以自定义格式生成时间戳,并将其保存为字符串。我试图将format生成的字符串存储到使用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))
datemake entry中的预期值应该与2014年7月30日星期三(GMT-7)的21:28:18类似,但我最后只得到了30,而不是剩下的部分。我还测试了返回的30的类型,它确实是一个整数,而不是应该的字符流(字符串)。正因为如此,我确信这和格式中的“~d”有关,但我可能错了。真的,我只是想通过一个格式化版本的系统时间来输入

(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)
    (declare (ignore dst-p))
    (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))    
然后

一些评论:

  • 在函数外声明常量
  • 不要使用
    defvar
    来声明局部变量,这与您的想法无关-使用
    let
    ,或者更好地避免它们
  • 不要在此处使用
    returnfrom
    ;该函数返回最后计算的表单,在本例中为
    format
  • 挑剔:如果有无法避免的未使用变量,请使用
    (声明(忽略…)
    ,以避免编译错误

  • 这段代码有很多问题,但最大的问题是
    格式
    的参数之一是
    (从…返回)

    将此与:

    CL-USER> (defun foo ()
               (list 1 2 3 (return-from foo 4)))
    FOO
    CL-USER> (foo)
    4
    
    大多数情况下,从函数返回值不需要做任何特殊的操作;最后一个表达式的值是函数的结果。这样就足够了,因为当format的第一个参数是nil时,您会得到一个字符串:

    (defconstant +day-names+                       ; Some people put + around constants
      '("Monday" "Tuesday" "Wednesday"             ; but it's not as a strong a convention
        "Thursday" "Friday" "Saturday" "Sunday"))  ; as * around dynamic variables.
    
    (defun date ()
      (multiple-value-bind (second minute hour date month year day-of-week dst-p tz)
          (get-decoded-time)
        (declare (ignore dst-p))
        ;; The value of (format ...) is returned from the date.
        (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))))
    


    另一方面,虽然这是可行的,但从长远来看,使用某些外部标准(例如XSD dateTimes指定的格式)中的日期可能更有用。为此,您可能会找到一些外部库,比如一些有用的库。

    好吧。[Dons代码审查帽]


    首先,让我们更加一致地进行缩进。在缩进方面,您确实比典型的lisp新手做得好得多,但将其中的大部分内容都放在了一列中。缩进级别可以为程序的控制流提供很多提示。一旦你习惯了,我是说

    (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))
    

    您可以但不应该在本地使用
    defcontent
    defvar
    。制作那些顶级表单,或者使用
    let
    将它们制作成本地定义。在您的例子中,
    常量
    作为一个全局变量是有意义的,而
    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)))))
    

    Lisp表单会自动返回它计算的最后一个值,但任何早期表单只会产生与值相反的副作用。具体来说,
    *DAY-NAMES*
    在日期开始时不做任何事情。另外,由于您似乎试图从
    date
    返回
    datetime
    ,因此不需要调用
    returnfrom
    。相反,只需计算
    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)))
    

    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))))
    
    此时,
    date
    似乎做了一些有意义的事情

    cl-user> (date)
    "15:39:12 Thursday 7/31/2014 (GMT-5)"
    cl-user> 
    

    由于您只是试图将一些值放入列表中,因此也不需要创建局部变量来保存
    make entry
    (date)
    的结果

    (defun make-entry (category subject idea info researched)
      (list :category category :subject subject :date (date) :idea idea :info info :researched researched))
    
    此时,
    make entry
    返回一个
    plist
    ,其
    :DATE
    值是
    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> 
    


    如果您正在跟踪,请记住,当您读入数据库时,需要再次解码以这种方式格式化的日期,假设您计划与它进行字符串比较以外的任何操作。因此,根据您的具体用例,存储
    (get universal time)

    的原始输出实际上可能更有意义,因为您不想“将其保存到流中”(我不确定这会是什么,除非以后可以从流中读取它);您正在尝试以字符串形式获取输出。
    cl-user> (date)
    "15:39:12 Thursday 7/31/2014 (GMT-5)"
    cl-user> 
    
    (defun make-entry (category subject idea info researched)
      (list :category category :subject subject :date (date) :idea idea :info info :researched researched))
    
    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> 
    
    (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))