为了让路径名足够抽象从而可以应用于广泛的文件系统。我们必须对多数跨越不同实现的常见操作提供一致接口。尽管你编写的代码都是“可移植的”,但是可能偶尔需要依赖于实现相关的功能或者为不同实现编写稍有差别的代码。Common lisp提供一种称为读取期条件化的机制,有条件的执行特性代码。
该机制由变量*feature* 和两个被lisp读取器所理解的附加语法构成(#+,#-)
*feature*是个符号的列表,可以在REPL中直接输入查看他的值,每个符号代表存在于当前实现或底层平台的一个“特性”,也就是标示用的。
根据特性表达式中的符号是否存在于*feature*求真假,如果在为真,否则为假。最简单的特性表达式是单个符号如sbcl,然后就是构造在or/and/not上的布尔表达式了(or allegro sbcl)。
#+ 之后的特性表达式为真,执行后面的代码。
#- 之后的特性表达式为假,执行后面的代码
比如某些代码只有在特性foo和bar存在时才执行#+(and foo bar) body在foo和bar都为假时执行#-(or foo bar) body
CL-USER> (defun foo()
#+allegro (format t "~s~%" 'allegro)
#+sbcl (format t "~s~%" 'sbcl)
#+clisp (format t "~s~%" 'clisp)
#+cmu (format t "~s~%" 'cmu)
#-(or allegro sbcl clisp cmu)(format t "~s~%" 'default))
FOO
CL-USER> (foo)
SBCL
NIL
二:列目录
函数Directory接受一种特殊类型的路径名,称为通配路径名,其带有一个或多个含有特殊值:wild组建。
注意directory应该用:absolute,因为我当时想的是他是相对于d盘而言,所以relative.但是如果这样的话,什么时候为绝对路径呢?我感觉先撇开磁盘,如果一个元素前面没有其它位置限定的话,就是绝对了,比如emacs前面就没有其他指定位置的名称了。
CL-USER> (make-pathname :directory '(:absolute "emacs")
:name :wild
:type :wild
:device "d")
#P"d:/emacs/*.*"
CL-USER> (make-pathname :directory '(:absolute "emacs")
:name :wild
:type "lisp"
:device "d")
#P"d:/emacs/*.lisp"
CL-USER> (make-pathname :directory '(:absolute "emacs")
:name "io"
:type :wild
:device "d")
#P"d:/emacs/io.*"
下面注意他会把peter解析成名字组件,并且替换成:wild
CL-USER> (make-pathname :name :wild
:type nil
:defaults "/home/peter")
#P"/home/*"
函数directory就是给你一个通配符然后输出显示所有符合当前模式的路径名。如果是单个的文件的话,显示的是文件格式,如果他是一个文件夹,就会输出显示为目录形式 #P"d:/emacs/emacs-24.1/"
CL-USER> (let ((wildcard (directory-wildcard "d:/emacs")))
#+(or sbcl cmu lispworks)
(directory wildcard))
(#P"d:/emacs/#file.lisp#" #P"d:/emacs/.emacs" #P"d:/emacs/.ido.last"
#P"d:/emacs/cd.lisp" #P"d:/emacs/cd2.lisp" #P"d:/emacs/do.lisp"
#P"d:/emacs/emacs-24.1/" #P"d:/emacs/file.fasl" #P"d:/emacs/file.lisp"
#P"d:/emacs/io.db" #P"d:/emacs/io.lisp" #P"d:/emacs/io.lisp~"
#P"d:/emacs/io2.db" #P"d:/emacs/io3.db" #P"d:/emacs/io4.db"
#P"d:/emacs/my-cds.db" #P"d:/emacs/my-cds.db2" #P"d:/emacs/my-cds.db3"
#P"d:/emacs/out.db" #P"d:/emacs/test.lisp" #P"d:/emacs/疑问.lisp")
下面是目录的两种表现形式,完全都是我们平常可能这样写,第一个看着跟file的表现方式似的,因为他后面没有斜杠,所以称它为文件形式的目录。而第二个情况就像我们平常比较熟悉的各个文件夹都是斜杠分开。正因为区分文件形式所以才会把目录的文件形式下的最后一个当成name来存放,而如果路径本身又指明了name的值,那么文件形式的最后一个位置的元素将被抛弃。
CL-USER> (make-pathname :directory '(:absolute "foo") :name "bar") #P"/foo/bar"
CL-USER> (make-pathname :directory '(:absolute "foo" "bar")) #P"/foo/bar/"
component-present-p
意思是当前这个组件是否有值。当值为:unspecific/nil时,表示当前元素是不存在的,也就是component-present-p为假。
CL-USER> (component-present-p :wild) T
CL-USER> (component-present-p :unspecific) NIL
CL-USER> (component-present-p nil) NIL
Directory-pathname-p
Directory-pathname-p目录形式就是路径名,深处意思是判断是不是整个路径名就是一个目录形式即name/type都是nile或则:unspecific。等价于component not present,所以求present的反就行。
CL-USER> (defun directory-pathname-p (p)
(and
(not (component-present-p (pathname-name p)))
(not (component-present-p (pathname-type p)))
p))
Wild-pathname-p
判断是不是有统配符。
CL-USER> (wild-pathname-p (make-pathname :directory '(:relative "/emacs")
:name "cd"
:type "lisp"
:device "d"))
NIL
CL-USER> (wild-pathname-p (make-pathname :directory '(:relative "/emacs")
:name "cd"
:type :wild
:device "d"))
(:WILD :WILD-INFERIORS)
Pathname-as-directory
Pathname-as-directory 就是说把pathname转化成目录形式,这有一个情况就是本身是一个具体到文件的(d:/emacs/file.lisp)还有个就是目录的文件形式(d:/emacs)
CL-USER> (pathname-as-directory "d:/emacs") #P"d:/emacs/"
CL-USER> (pathname-as-directory "d:/emacs/cd.lisp") #P"d:/emacs/cd.lisp/"
CL-USER> (pathname-as-directory "d:/emacs/") #P"d:/emacs/"
CL-USER> (pathname-as-directory "d:/emacs/.lisp") #P"d:/emacs/.lisp/"
Pathname-as-file
Pathname-as-file 就是把路径名转化为文件形式,同样也有几种特殊情况。本身是目录形式(d:/emacs/)
CL-USER> (pathname-as-file "d:/emacs/") #P"d:/emacs"
CL-USER> (pathname-as-file "d:/emacs/file.lisp") #P"d:/emacs/file.lisp"
CL-USER> (pathname-as-file "d:/home/peter") #P"d:/home/peter"
directory-wildcard
directory-wildcard 函数就是把目录转化为一个通配符形式,因为我们前面已经执行了pathname-as-directory使所有的路径名都转化为了目录形式,即name/type都为了nil,进而都为:wild。他在处理时候判断路径名是不是含有:wild值,如果有就会报错。
CL-USER> (wild-pathname-p (make-pathname :directory '(:absolute "emacs")
:name :wild
:type "lisp"
:device "d"))
(:WILD :WILD-INFERIORS)
根据上面我们知道pathname-as-directory 会把一个路径名转化为一个目录形式,也就是说name/type都为nil了,现在你在这个directory-wildcard函数里面把name/type都设置为了:wild,现在如果我想输出来所有后缀为lisp的怎么办?然后再加上前面有个问题就是如果有后缀一般就是文件形式了,现在你也给转换成了目录形式,我感觉是不是可以单独把有后缀的分出来。
但是你就像没有后缀type,但是仍旧是一个file怎么办?如何彻底解决?
CL-USER> (defun directory-wildcard (dirname)
(make-pathname :name :wild
:type :wild
:defaults "pathname-as-directory dirname"))