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