Функциональное программирование

       

Чтение и запись информации в файлы


ЛЕКЦИЯ 10.

Чтение и запись информации в файлы


Содержание





10.1 Задание параметров при определении функций.

При определении функции можно использовать механизм ключевых слов для того чтобы при вызове функций аргументы трактовать по разному.

С помощью ключевых слов в лямбда-списке можно выделить

  • необязательные аргументы (optional)
  • параметр, связываемый с хвостом списка аргументов изменяющейся длины (rest)
  • ключевые параметры (key)

    Ключевые слова начинаются с символа & и их записывают перед соответствующими параметрами в лямбда-списке.

    Действие ключевого слова распростроняется до следующего ключевого слова.

    Параметры, перечисленные в лямбда-списке до первого ключевого слова, являются обязательными.


    10.1.1 Необязательные параметры &optional

    Вы можете определить необязательные аргументы для вашей функции. Любой аргумент после символа &optional необязательный:

    * ( Defun bar ( x &optional y) ( if y x 0 )) bar * ( Defun baaz ( &optional ( x 3 ) ( z 10 )) ( + x z) ) BAAZ * ( bar 5 ) 0 * ( bar 5 t) 5 * ( Baaz 5 ) 15 * ( Baaz 5 6 ) 11 * (Baaz) 13

    Можно вызывать функцию bar или с одним или с двумя аргументами. Если она вызвана с одним аргументом, x будет связано со значением этого аргумента и незаданный аргумент y будет связан с nil; если она вызвана с двумя аргументами,x и y будут свя- заны со значениями первого и второго аргумента, соответственно.

    Функция baaz имеет два необязательных аргумента. Кроме этого она определяет недостающие знaчения для каждого из них: если пользователь определит только один аргумент, z будет связано с 10 вместо nil, и если пользователь не определит никаких аргументов, x будет связана с 3 и z с 10.

    Такое определение значений называется определение по умолчанию.


    10.1.2 Переменное количество аргументов &rest

    Вы можете задавать вашу функцию принимающей любое число аргументов, заканчивая список аргументов &rest параметром.

    LISP будет собирать все аргументы не попавшие в обязательные параметры в список и связывать &rest параметр с этем списком.



    Итак:



    * ( Defun foo ( x &rest y) y)

    FOO

    * ( Foo 3 )

    NIL

    * ( Foo 4 5 6 )

    (5 6)

    * ( defun fn ( x &optional y &rest z)) (list x y z)) fn

    * (fn 'a)

    (A NIL NIL)

    * ( a b (c d))



    10.1.3 Ключевые параметры Можно задать функции другой вид необязательного аргумента называемого аргументом ключевого слова. Пользователь может задавать эти аргументы в последующем в любом порядке, потому что они маркированы ключевыми словами. Символы t и nil называются константами-символами, потому-что они при выполнении дают сами себя.

    Существует целый класс таких символов, которые называются ключевыми словами; любой символ, чье имя начинается с двоеточия является ключевым словом.

    (Ниже приведены некоторые использования ключевых слов).

    Примеры:



    * :this-is-a-keyword

    :THIS-IS-A-KEYWORD

    * :so-is-this :SO-IS-THIS

    * :me-too :ME-TOO

    ( Defun foo ( &key x y) ( cons x y) )

    FOO

    * ( Foo :x 5 :y 3 )

    (5 . 3)

    * ( Foo :y 3 :x 5 )

    (5 . 3)

    * ( Foo :y 3 )

    ( NIL. 3 )

    * (Foo)

    (NIL)

    &key параметр может иметь также значение по умолчанию:

    * ( Defun foo ( &key ( x 5 )) x )

    FOO

    * ( Foo :x 7 )

    7

    * (Foo)

    5

    (defun test ( x &optional (y 3) (z 4) &rest a) (cons z ( list x a y)))

    (test 1 2 3)

    (test 1)

    (test 3 4 5)

    (test 3 2 1 1 2 3)



    10.2 Входные и выходные потоки. При вводе и выводе информации в Лиспе используется понятие потоков - stream

    Для потока определены ИМЯ , операции открытия open операции закрытия clouse направления output и input

    10.3 Определение выходных и входных потоков.

    Для открытия файла для записи задается его имя, производится операция open и указывается направление output:

    (setq our-output-stream (open "sesame" :direction :output))

    Зададим

    (setq s 'e)

    Можно вывести это значение в файл

    (princ s our-output-stream) ;

    Можно занести список

    (print '(a b c d) our-output-stream)

    Чтобы правильно закрыть поток необходимо в конец поместить

    (terpri our-output-stream)

    Затем файл закрывается

    (close our-output-stream)



    Можно посмотреть информацию в файле.

    Откроем файл для чтения:

    (setq our-input-stream (open "sesame" :direction :input))

    Прочитае информацию

    (read our-input-stream)

    Закроем файл

    (close our-input-stream)



    10. 4 Чтение символов из файла

    Предположим, что в файле хранится символьная информация, необходимая нам для обработки. Причем нас интересует каждый символ в файле. До сих пор мы могли вводить только атомы, числа и списки.

    Сформируем файл

    Пусть

    (setq s "---+++")

    (setq p "+++---")

    Определим поток вывода



    (setq our-output-stream (open "picture.spl" :direction :output)) (princ s our-output-stream) ; записываем первую стороку (terpri our-output-stream) ; заканчиваем ее (princ p our-output-stream) ; записываем вторую строку (terpri our-output-stream) ; заканчиваем файл


    Тепрь файл закрывается

    (close our-output-stream)

    В файле теперь находится

    ---+++ +++---


    Для чтения символов из файла будем использовать функцию

    (READ-CHAR )

    Данная функция позволяет читать печатные символы ( CHAR) из файла. В качестве значения получается десятичное представление кода символа.

    Используе эту функцию для посимвольного ввода информации из файла для ее последующего анализа

    Определим

    (setq our-input-stream (open "picture.spl" :direction :input))

    Для чтения символа используем

    (read-char our-input-stream)

    Будем получать последовательность значений

    43 43 43 45 45 45 10 и т.д.

    Для восстановления содежимого файла применяется перекодировка

    (setq x (read-char our-input-stream)

    То содержимое x можно показать



    (cond (( = x 43) (prin1'+)) (( = x 45) (prin1 '-)) (( = x 10 ) (terpri)))


    Можно представить информацию без искажений, если использовать цикл



    (loop (progn (setq x (read-char our-input-stream) ) (cond (( = x 43) (prin1'+)) (( = x 45) (prin1 '-)) (( = x 10 ) (terpri))))))


    После вывода имеем



    ---+++ +++---


    Закрытие входного потока

    (close our-input-stream)

    Для поиска конца файла можно анализировать ошибку чтения, но лучше знать длину файла до начала работы с ним.




    Содержание раздела