Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Practical Common Lisp: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

If you try to use this pathname as an argument to OPEN , the missing components, such as the directory, must be filled in before Lisp will be able to translate the pathname to an actual filename. Common Lisp will obtain values for the missing components by merging the given pathname with the value of the variable *DEFAULT-PATHNAME-DEFAULTS* . The initial value of this variable is determined by the implementation but is usually a pathname with a directory component representing the directory where Lisp was started and appropriate values for the host and device components, if needed. If invoked with just one argument, MERGE-PATHNAMES will merge the argument with the value of *DEFAULT-PATHNAME-DEFAULTS* . For instance, if *DEFAULT-PATHNAME-DEFAULTS* is #p"/home/peter/", then you'd get the following:

(merge-pathnames #p"foo.txt") ==> #p"/home/peter/foo.txt"

Two Representations of Directory Names

When dealing with pathnames that name directories, you need to be aware of one wrinkle. Pathnames separate the directory and name components, but Unix and Windows consider directories just another kind of file. Thus, on those systems, every directory has two different pathname representations.

One representation, which I'll call file form , treats a directory like any other file and puts the last element of the namestring into the name and type components. The other representation, directory form , places all the elements of the name in the directory component, leaving the name and type components NIL . If /foo/bar/is a directory, then both of the following pathnames name it.

(make-pathname :directory '(:absolute "foo") :name "bar") ; file form

(make-pathname :directory '(:absolute "foo" "bar")) ; directory form

When you create pathnames with MAKE-PATHNAME , you can control which form you get, but you need to be careful when dealing with namestrings. All current implementations create file form pathnames unless the namestring ends with a path separator. But you can't rely on user-supplied namestrings necessarily being in one form or another. For instance, suppose you've prompted the user for a directory to save a file in and they entered "/home/peter". If you pass that value as the :defaultsargument of MAKE-PATHNAME like this:

(make-pathname :name "foo" :type "txt" :defaults user-supplied-name)

you'll end up saving the file in /home/foo.txtrather than the intended /home/peter/foo.txtbecause the "peter"in the namestring will be placed in the name component when user-supplied-nameis converted to a pathname. In the pathname portability library I'll discuss in the next chapter, you'll write a function called pathname-as-directorythat converts a pathname to directory form. With that function you can reliably save the file in the directory indicated by the user.

(make-pathname

:name "foo" :type "txt" :defaults (pathname-as-directory user-supplied-name))

Interacting with the File System

While the most common interaction with the file system is probably OPEN ing files for reading and writing, you'll also occasionally want to test whether a file exists, list the contents of a directory, delete and rename files, create directories, and get information about a file such as who owns it, when it was last modified, and its length. This is where the generality of the pathname abstraction begins to cause a bit of pain: because the language standard doesn't specify how functions that interact with the file system map to any specific file system, implementers are left with a fair bit of leeway.

That said, most of the functions that interact with the file system are still pretty straightforward. I'll discuss the standard functions here and point out the ones that suffer from nonportability between implementations. In the next chapter you'll develop a pathname portability library to smooth over some of those nonportability issues.

To test whether a file exists in the file system corresponding to a pathname designator—a pathname, namestring, or file stream—you can use the function PROBE-FILE . If the file named by the pathname designator exists, PROBE-FILE returns the file's truename , a pathname with any file system-level translations such as resolving symbolic links performed. Otherwise, it returns NIL . However, not all implementations support using this function to test whether a directory exists. Also, Common Lisp doesn't provide a portable way to test whether a given file that exists is a regular file or a directory. In the next chapter you'll wrap PROBE-FILE with a new function, file-exists-p, that can both test whether a directory exists and tell you whether a given name is the name of a file or directory.

Similarly, the standard function for listing files in the file system, DIRECTORY , works fine for simple cases, but the differences between implementations make it tricky to use portably. In the next chapter you'll define a list-directoryfunction that smoothes over some of these differences.

DELETE-FILE and RENAME-FILE do what their names suggest. DELETE-FILE takes a pathname designator and deletes the named file, returning true if it succeeds. Otherwise it signals a FILE-ERROR . [161] See Chapter 19 for more on handling errors.

RENAME-FILE takes two pathname designators and renames the file named by the first name to the second name.

You can create directories with the function ENSURE-DIRECTORIES-EXIST . It takes a pathname designator and ensures that all the elements of the directory component exist and are directories, creating them as necessary. It returns the pathname it was passed, which makes it convenient to use inline.

(with-open-file (out (ensure-directories-exist name) :direction :output)

...

)

Note that if you pass ENSURE-DIRECTORIES-EXIST a directory name, it should be in directory form, or the leaf directory won't be created.

The functions FILE-WRITE-DATE and FILE-AUTHOR both take a pathname designator. FILE-WRITE-DATE returns the time in number of seconds since midnight January 1, 1900, Greenwich mean time (GMT), that the file was last written, and FILE-AUTHOR returns, on Unix and Windows, the file owner. [162] For applications that need access to other file attributes on a particular operating system or file system, libraries provide bindings to underlying C system calls. The Osicat library at http://common-lisp.net/project/osicat/ provides a simple API built using the Universal Foreign Function Interface (UFFI), which should run on most Common Lisps that run on a POSIX operating system.

To find the length of a file, you can use the function FILE-LENGTH . For historical reasons FILE-LENGTH takes a stream as an argument rather than a pathname. In theory this allows FILE-LENGTH to return the length in terms of the element type of the stream. However, since on most present-day operating systems, the only information available about the length of a file, short of actually reading the whole file to measure it, is its length in bytes, that's what most implementations return, even when FILE-LENGTH is passed a character stream. However, the standard doesn't require this behavior, so for predictable results, the best way to get the length of a file is to use a binary stream. [163] The number of bytes and characters in a file can differ even if you're not using a multibyte character encoding. Because character streams also translate platform-specific line endings to a single #\Newline character, on Windows (which uses CRLF as its line ending) the number of characters will typically be smaller than the number of bytes. If you really have to know the number of characters in a file, you have to bite the bullet and write something like this: (with-open-file (in filename) (loop while (read-char in nil) count t)) or maybe something more efficient like this: (with-open-file (in filename) (let ((scratch (make-string 4096))) (loop for read = (read-sequence scratch in) while (plusp read) sum read)))

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x