⌨ Labor omnia vincit ☮

(format t “more than 80 characters per line”)

Posted in Lisp by anaumov on 29.08.2015

csvСтолкнулся сегодня с интересной особенностью функции format в Common Lisp. По умолчанию она выводит только по 80 символов на строку, а остальную часть переносит на следующую. Причина такого поведения, как вы уже догадались, историческая, и заключается в том, что раньше большинство UNIX терминалов использовало только 80-символьные строки на экране (наследие перфокарт IBM?).

До этого мне никогда не нужны были строки длинее, но сегодня я решил переписать один из своих скриптов, а именно: в качестве вывода использовать CSV– вместо XLS-файла. Так как скрипт просто генерировал таблицу, то я не стал для этого подключать целую библиотеку для работы с CSV, а решил самому написать функцию для создания файлов этого формата.

CSV означает Comma-Separated Values, т.е. это простейший формат таблиц, где существует только два правила: каждая новая строка в нашем файле будет новой строкой в таблице; для сток должен указывается так называемый разделитель (по умолчанию это запятая), который будет делить строку на ячейки (или столбцы). Другими словами, если в нашем выводе встречается символ новой строки, CVS перенесет весь остальной вывод на новую строку и продолжит заполнять ячейки уже на ней.

Попробуем воспроизвести проблему. Вот код, который по умолчанию будет работать не так как мы ожидали бы:

        (setq  L '("AAAAAAAAAA#"))
        (nconc L '("BBBBBBBBBB#"))
        (nconc L '("CCCCCCCCCC#"))
        (nconc L '("DDDDDDDDDD#"))
        (nconc L '("EEEEEEEEEE#"))
        (nconc L '("FFFFFFFFFF#"))
        (nconc L '("GGGGGGGGGG#"))
        (format t "L = ~A~%" L)

Как видете, несмотря на то, что после F-строки никакого символа новой строки нет, в выводе мы получаем 2 строки:

L = (AAAAAAAAAA# BBBBBBBBBB# CCCCCCCCCC# DDDDDDDDDD# EEEEEEEEEE# FFFFFFFFFF#
     GGGGGGGGGG#)

В Common Lisp есть целая серия переменных, отвечающих за печать вывода на экран:

  (format t ";;           *print-array* = ~a~%" *print-array*)
  (format t ";;            *print-base* = ~a~%" *print-base*)
  (format t ";;            *print-case* = ~a~%" *print-case*)
  (format t ";;          *print-circle* = ~a~%" *print-circle*)
  (format t ";;          *print-escape* = ~a~%" *print-escape*)
  (format t ";;          *print-gensym* = ~a~%" *print-gensym*)
  (format t ";;          *print-length* = ~a~%" *print-length*)
  (format t ";;           *print-level* = ~a~%" *print-level*)
  (format t ";;           *print-lines* = ~a~%" *print-lines*)
  (format t ";;     *print-miser-width* = ~a~%" *print-miser-width*)
  (format t ";; *print-pprint-dispatch* = ~a~%" *print-pprint-dispatch*)
  (format t ";;          *print-pretty* = ~a~%" *print-pretty*)
  (format t ";;           *print-radix* = ~a~%" *print-radix*)
  (format t ";;        *print-readably* = ~a~%" *print-readably*)
  (format t ";;    *print-right-margin* = ~a~%" *print-right-margin*))

По умолчанию *print-pretty* установленно в T. Изменение на NIL решит нашу проблему: снимет ограничение на 80 символов для строки:

(setq *print-pretty* 'nil)

После этого мы сами сможем определять когда именно должна начаться следующая строка. Казалось бы не слишком важная информация, но если вы решили создать CVS-файл самому (не используя при этом какие-то дополнительные библиотеки), без нее не обойтись😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: