ЛИСП осначает "обработку списков" или " программирование списков
". В ЛИСПЕ, основным обрабатывающим средством есть " нахождение
значения объекта "; то-есть обработка - метод которым Lisp опре-
деляет значение любого выражения, сложного объекта, или простого
объекта.
ОБЪЕКТЫ
Имеются два общих типа объектов в AutoLISP - АТОМЫ и СПИСКИ. Ато-
мы - простые объекты; списки - сложные объекты.
Атомы и списки взаимно исключающие. Что-нибудь что является ато-
мом не может быть список, и наоборот ( здесь одно исключение ко-
торое доказывает это правило, объект Нуль; мы будем рассказывать
о нем позже ).
АТОМЫ
Атомы могут быть целым, вещественным числом, текстовой строкай,
функцией AutoLISP, символом, или специальными объектами которые
соответствуют примитивам AutoCAD, наборам выбора, и файлам.
Все они - атомы:
1 ; Целое число 1
4.5 ; Вещественное число 4.5
" A String of Pearls " ; Текстовая строка
Setq ; AutoLISP функция
Ename ; Определяемый пользователем символ
ЗНАЧЕНИЯ AТОМОВ
Значения любого атома, за исключением функций AutoLISP и опреде-
ляемых пользователем символов, является он сам. Например, атом 1
имеет значение 1; Атом 4.5 имеет значение 4.5; атом " A String of
Pearls " имеет значение " A String of Pearls ".
Вы можете определять значение любого атом в командной строке
AutoCAD. Напечатайте знак восклицания "!" сопровождаемый атомом.
AutoLISP будет находить и возвращать значение атома в командную
строку. Например, это выражение находит значение атома ( и вещес-
твенное число ) 4.5:
Command: !4.5
4.5
СПИСКИ
Списки - сложные объекты, упоминаемые в некоторых описаниях как
символические выражения, или " s-выражения ".
Списки сформирова-
ны вне атомов и ( или ) других списков. Список синтаксически
прост; он должен ограничиваться согласованными круглыми скобками,
и объекты внутри списка должны отделяться от друга друга пробелом.
Примеры списков:
( + 1 3 ) ; Сложить 1 и 3
( - 9 5 ) ; Вычесть 5 из 9
( + 1 ( + 2 3 )) ; Добавить 1 к результату сложения 2 и 3
Что-нибудь ограниченное согласованными круглыми скобками должно
быть списком; что-нибудь не ограниченное согласованными круглыми
скобками должно быть атомом.
ЭЛЕМЕНТЫ СПИСКОВ
Индивидуальные члены списка известны как элементы. Ниже пример
списка с тремя элементами, каждый из которых - атом:
(+ 1 2)
Элементы списков могут быть или атомами или другими списками. Ни-
же пример списка с тремя элементами; два - атомы, третий - самос-
тоятельный список трех элементов:
(+ 1 (+ 2 3))
| | \ /
| | \ /
| | |
Элементы
Элементы списка должны отделяться от друга друга по крайней мере
одним пробелом. Нет никакого ограничения числа пробелов отделяю-
щих элементы, но должен иметься по крайней мере один. Это совер-
шенно допустимый список:
(+ 1 (+ 1 3))
ПУСТОЙ СПИСОК
Имеется один объект в AutoLISP который является и атомом и спис-
ком. Это - пустой список; то-есть список не имеющий никаких эле-
ментов, обычно называемый НУЛЬ (NIL).
( ) или нуль
Нуль ( пустой список ) в AutoLISP не " никакое значение ". Когда
объект в AutoLISP не имеет никакого значение, тогда значение
объекта - нуль.
УПРАЖНЕНИЕ
Которые из этих объектов являются атомами и которые являются
списками?
ПРЕДИКАТЫ, ЛОГИЧЕСКИЕ ОПЕРАТОРЫ И УСЛОВНЫЕ ВЫРАЖЕНИЯ
УСЛОВНЫЙ ПЕРЕХОД
Способность исследовать состояние одного или больше назначений (
или переменных ) и принимать решение основанное на том, выпол-
няется или нет выражение в программе - фундаментальное и мощное
средство в AutoLISP. Эта форма принятия решения может оцени-
ваться как условный переход, то-есть переход в логике программы,
говорящий, выполнять или не выполнять специфическое выражение
программы, или выполнять одно выражение программы скорее чем дру-
гой, основанный на некотором существующем условии.
Вы и я принимаем эти решения все время. Если сегодня солнечно, мы
не будем брать с собой на работу зонтик. Если бензин стоит дешев-
ле на одной бензоколонке, тогда Мы будем приобретать его там, а
не на другой, где он дороже.
В обеих предыдущих примерах, слово "если" используется как услов-
ное выражение, то-есть функция которая выполняет тест чтобы опре-
делить существует ли специфическое состояние или условие. Фун-
кция AutoLISP IF имеет фактически то же самое значение что и сло-
во "если", используемое в предыдущих, реальных примерах.
Условный оператор IF
Функция IF используется чтобы проверить состояние одиночного ус-
ловия. Если условие сравнивается с не-нулевым значением, то-есть
чему-нибудь НE нуль, тогда выражение программы немедленно после
проверки будет выполняться.
( if <выражение проверки> <выражение> [<выражение>] )
Должно существовать одно выражение после выражения проверки. Мо-
жет существовать также второе, необязательне выражение, которое
будет оцениваться если выражение проверки возвращает нуль.
Например определеим функцию, которая бы проверяла, большее ли 0
значение переменной X. Если так, тогда это вывести на дисплей "X
greater than 0".
Создайте файл с именем GREATER.LSP и определите эту функцию.
(defun GREATER ()
(if
(> x 0)
(prompt "\nX is greater than 0.")
)
(prin1)
)
Command: (setq x 1)
1
Command: (load "greater")
GREATER
Command: (greater)
X is greater than 0.
Command: (setq x -1)
-1
Command: (greater)
Имеются несколько вещей, которые Вы можете выполнить чтобы де-
лать функцию GREATER более универсальной. Сначала, сделайте зна-
чение для выражения проверки аргументом функции, чтобы GREATER
больше не зависила от значения специфической глобальной перемен-
ной X. Затем, добавьте второй оператор к выражению IF который бы
выводил на экран сообщение, если значение требуемого параметра
МЕНЬШЕ или РАВНО нулю.
Отредактируйте файл GREATER.LSP и сделают эти два изменения в
функции GREATER.
(defun GREATER (x)
(if
(> x 0)
(print "\nArgument is greater than 0.")
(print "\nArgument is less than or equal to 0.")
)
(prin1)
)
Command: (load "greater")
GREATER
Command: (greater 1)
Argument is greater than 0.
Command: (greater -1)
Argument is less than or equal to 0.
Command: (setq y 1)
1
Command: (greater y)
Argument is greater than 0.
ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ ОПЕРАТОРА IF
Одна из недавних тем на CompuServe ADESK Форуме были желание из-
менять команду END, что бы она запрашивала у пользователя, сохра-
нять или нет текущее состояние рисунка перед выходом из AutoCAD,
тем же самым способом как запрашивает пользователя команда QUIT.
В следующем примере, Вы будете записывать функцию AutoLISP заме-
няющую родную команду END AutoCAD, и делающую неопределенной род-
ную команду END, чтобы AutoCAD использовал функцию AutoLISP вмес-
то нее.
Новая функция будет поэтому определена так, что сможет вызы-
ваться непосредственно из командной строки AutoCAD без включения
в круглые скобки, и будет самостоятельно вызывать местную коман-
ду END ( независимо от того была ли команда END сделана неопреде-
ленной ) указав перед именем команды точку ".".
Создайте новый файл назвав его END.LSP и добавте туда эту функцию.
(defun C:END (/ usr)
; Запросить пользователя и получить ответ
(setq usr (getstring "\nReally want to END the drawing? "))
; Преобразовать его ответ в символы верхнего регистра
(setq usr (strcase usr))
; Проверяют был ли его ответ "y" или "Y"
(if
(equal "Y" usr)
; Если это было, тогда завершить чертеж, иначе вывести сообщение
(command ".END")
(prompt "\nRemaining in drawing editor.")
)
; тихий выход из функции
(prin1)
)
Родная команда END может отключаться командой UNDEFINE и поэтому
может заменяться функцией AutoLISP C:END .
Command: UNDEFINE
Command name: END
Command: (load "end")
C:END
Command: END
Really want to END the drawing? n
Remaining in drawing editor.
Command: END
Really want to END the drawing? y
Для эффективности и не выполненя ненужного связывания переменных,
которое может быть относительно дорого в смысле компьютерного
времени, функция C: END может также быть написана так:
(defun C:END ()
(if
(eq "Y"
(strcase
(getstring "\nReally want to END the drawing? ")
)
)
(command ".END")
(prompt "\nRemaining in drawing editor.")
)
(prin1)
)
Однако, поскольку Вы только начинаете изучать AutoLISP, очевидно
что Вы будете использовать много операций связывания переменных,
так как это поможет Вам лучше разбираться в ваших программах.
Имеются много средств, которые позволят Вам в AutoLISP записать
более эффективный код, но пока Вы имеете только твердое понима-
ние базисных механизмов, такое усилие - вероятно будет непроизво-
дительно. Кто заботится, использовались ли дополнительные 40 мил-
лисекунд компьютерного времени для связыванием переменной, это
строго говоря не столь важно если оно делает логику программы бо-
лее понятной для Вас?
Упражнения
1. Записать новую функцию HIGHER. Вот что она должна делать:
a) Запросить у пользователя две точки.
b) Сохранить значения обеих точек.
c) Проверить значения Y обеих точек.
d) Если значение Y первой точки большее, напечатать сообще-
ние, указывающие пользователю, что первая точка выше.
e) Если значение Y второй точки большее, напечатайте сообще-
ние, указывающие пользователю, что вторая точка выше.
Функции который Вы можете захотеть использовать - GETPOINT, IF,
DEFUN, CAR, CDR, и >.
Обратите Внимание что Вы можете включать два раздельных условных
оператора IF, или описать два возможных ответа как два выражения
после выражения проверки в одиночном условном операторе IF. Пос-
ледний случай обычно упоминается как оператор IF-THEN-ELSE.
( if
< это выражение проверки истинно >
< тогда выполнить это выражение >
< иначе выполнить это выражение >
)
КАЖДЫЙ ОБЪЕКТ ИМЕЕТ ЗНАЧЕНИЕ
Имеются два типа объектов в AutoLISP; атомы и списки. Каждый атом
и каждый список имеет значение. Процесс которым AutoLISP опреде-
ляет значение объекта называется "оценка".
ОЦЕНКА АТОМОВ
атомы - простые объекты, и они оцениваются используя простые пра-
вила согласно их типу данных. Имеются другие типы данных кроме
перечисленных ниже; они будут исследоваться подробно в следующем
уроке. Значение символа не может быть очевидно пока процесс "свя-
зывания" не обсуждается наряду с оценкой списков.
Тип атома Пример Оценка Значение
Целое 1 Значение - он сам 1
Вещественное 4.5 Значение - он сам 4.5
Строка "text" Значение - он сам "text"
Символ X Текущее связывание будет назначен
любой тип
ОЦЕНКА СПИСКОВ
Значение списка может определяться одним из двух способов; или
принимая список таким как он есть, или оценивая список. Первый
метод будет давать отличные результаты, или отличное значение от
второго.
Если список принимается таким как он есть, тогда значение - он
сам. Это будет становиться более понятно после объяснения фун-
кции (quote) позже в этом уроке.
Списки оцениваются согласно первому элементу списка. Если первый
элемент - имя внутренней функции AutoLISP, или процедуры, остаю-
щиеся элементы списка передаются процедуре как формальные пара-
метры и оцениваются ею.
Пример: список трех элементов, процедуры + и целых чисел 1 и 2.
(+ 1 2)
Далее рассатривается процесс оценки которым AutoLISP определяет
значение этого списка. Все оценки того же самого списка происхо-
дят точно так же, каждый раз. Тот же самый общий процесс оценки
применяется к каждому списку который может быть, и оценивается
точно таким же способом, каждый раз.
(+ ..
AutoLISP рассматривает первый элемент списка, где как ожидается
можно найти функцию. Функции - любые внутренние функции AutoLISP,
или процедуры, или определяемые пользователем функций созданных
функциями (lambda) или (defun).
AutoLISP оценивает функциональный, или первый элемент список.
Функция оценивается для определения набора команд который сооб-
щает AutoLISP что делать далее.
( Не изящно ли это? Каждое сложное выражение в AutoLISP несет
собственные команды обработки вместе с ним, в том же самом месте
каждый раз; в голове списка. )
В этом случае функции + оценивает набор команд который сообщает
AutoLISP, "Иди искать значение каждого последующего элемента в
этом списке. Когда все сделаешь, сложи все значения и возврати
результат как значение всего списка. "
(.. 1 ..)
Следуя набору команд, AutoLISP находит значение следующего эле-
мента в списке, атома и целого числа 1. Целые Числа оценивают как
такими как они есть, так что AutoLISP сохраняет значение 1 и про-
должает следовать набору команд.
(.. .. 2)
Значение целого числа 2 - 2. AutoLISP сохраняет это значение и
продолжает далее.
Элементы в списке после функции - параметры функции; то-есть они
- данные по которым функция выполняется. При не нахождении дру-
гих элементов в списке, или параметров функции, AutoLISP заканчи-
вает выполнение команд которые он получил оценивая функцию и
складывает значения аргументов, возвращая целое число 3 как зна-
чение списка.
Command: ( + 1 2 )
3
БОЛЕЕ СЛОЖНЫЙ ПРИМЕР
AutoLISP ( любой ЛИСП, фактически ) всегда оценивает элементы в
списке справа налево. Вы можете оценивають эти элементы вложен-
ным способом, изнутри, однако это неправильно. Это может быть
удобно для нас в некоторых случаях чтобы следить за процессом
оценки изнутри списка, но AutoLISP так никогда не оценивает спи-
сок. Он всегда работает справа налево.
Рассмотрим список трех элементов, функция ( или процедуры ) +,
атома 1, и списка ( + 2 3 ).
(+ 1 (+ 2 3))
AutoLISP оценивает этот список следующим образом:
(+ ..
AutoLISP рассматривает первый элемент списка и оценивает это. Так
как это - функция, то возвращает как значение набор команд по ко-
торому AutoLISP должен действовать далее.
(.. 1 ..
После команд для функции + , AutoLISP находит значение второго
элемента в списке (первый аргумент функции + ), атом 1, запоми-
нает его значение, и продолжает дальше.
(.. .. (+ 2 3)
AutoLISP находит значение третьего элемента в списке, второй ар-
гумент функции + . Третий элемент - самостоятельный список. Как
AutoLISP оценивает список?
Во первых, оценивает функцию + и получает команды. Далее находит
значения параметров, складывает их, и возвращает результат, кото-
рый в этом случае является целым числом 5.
Если элементов в списке больше нет, AutoLISP заканчивает набор
команд складывая значение двух элементов вместе и возвращает зна-
чение целого числа 6.
(+ 1 (+ 2 3))
| \ /
| \ /
| | ------------ Значение объекта - целое число 5
| ----------------- Значение объекта - целое число 1
ПРИНЯТИЕ СПИСКА ТАКИМ КАК ОН ЕСТЬ
Функция (quote) может использоваться чтобы возвратить список (
или атом ) неоцененный; то-есть таким как он есть. (quote) берет
один параметр, и возвращает как значение неоцененный параметр.
Например, это выражение возвращает список ( 1.0 2.0 3.0 ) таким,
какой он есть:
Command: ( quote ( 1.0 2.0 3.0 ))
(1.0 2.0 3.0)
Что случиться если у AutoLISP запросят оценить список?
Почему?
Command: ( 1.0 2.0 3.0 )
?
СВЯЗЫВАНИЕ СИМВОЛА И ЗНАЧЕНИЮ
Связывание - процесс в котором значение присваивается определяе-
мому пользователем символу, или переменной.
В AutoLISP, мы сооб-
щаем что символ ( или переменная ) связывается со значению. Это
сравнимо с высказыванием на языке БЕЙСИК что значение равно пере-
менной.
Функция (setq) используется чтобы связать символ ( или перемен-
ную ) со значению. Например, это выражение связывает символ X и
значение 4.5.
Command: ( setq x 4.5 )
4.5
Command:! X
4.5
В БЕЙСИКЕ, та же самая операция могла выражаться как:
LET X = 4.5
Значение (setq) - набор команд который указывает:
Найти значение второго параметра функции setq ( третий элемент в
списке ). Берется первый параметр как он есть, не оценивая его.
Связать первый параметр со значением второго параметра.
УПРАЖНЕНИЕ
Который из этих списков может оцениваться и который должен прини-
маться как он есть ?
Используя функции (setq) и (quote) ( как необходимо ), свяжите
переменную X со следующими значениями. Проверьте значение пере-
менной используя ! для определения результата.
1. 1
2. 4.5
3. "text"
4. (1.0 2.0 3.0)
Далее: Типы Данных
Ответ на упражнения Урока 1 :
1. Атом
2. Атом
3. Список
4. Атом
5. Список
6. Атом и список
1. 4.5
2. "text"
3. 17
4.
5. nil
6. nil
1. 3
2. 3
3. 3
4. 5
5. 4
6. Ни один
ТИПЫ ДАННЫХ
Имеются два вида объектов в AutoLISP.
Атомы - простые объекты;
списки - сложные объекты, ограниченные круглыми скобками. Среди
простых объектов, имеются большое количество под-категорий извес-
тных как типы данных.
Чистое понимание типов данных в AutoLISP очень важно. Наряду с их
прародителями классами объектов атомами и списками, они форми-
руют важные составляющие блоки для всех программ AutoLISP.
Типы данных описывают характер данных, что атом должен содержать,
и количество места ( или памяти ) которое AutoLISP должен выде-
лить чтобы создать атом и сохранить его значение. Этот урок бу-
дет сконцентрирован на вышеупомянутой теме; управление памятью
будет обсуждаться в следущих уроках.
Ниже - список типов данных поддерживаемы AutoCAD версии 10. Все
за исключением одной под-категории атомов; исключение - тип дан-
ных "list". Перечисляются квалифицируемые как явные типы данных.
* Список
* Символы
* Строки
* Вещественные числа
* Целые числа
* Описатели файла
* "Имена" примитивов AutoCAD
* Наборы выбор AutoCAD
* встроенные функции
ОПРЕДЕЛЕНИЕ ТИПОВ ДАННЫХ
Функция AutoLISP (type) может использоваться чтобы определить тип
данных любого объекта. (type) берет один требуемый параметр, и
возвращает символ, который указывает тип данных параметра.
Например, определить тип данных целого числа 1.
Команда: ( type 1 )
INT
ПРИМЕРЫ ТИПОВ ДАННЫХ
Пример кода AutoLISP, который связывает переменную x с рядом
объектов с различными типами данных и определяет тип данных свя-
зывания с помощю функции (type). Вы можете захотеть набрать выра-
жения в командной строке AutoCAD.
В случаях где шестнадцатеричный номер появляется как часть типа
данных, невозможно точно представить номер, поскольку он изме-
няется время от времени. Взамен, номер представляется в примерах
просто как " xxxx ".
СПИСОК
Command: ( setq x ( quote ( 1 2 3 )))
(1 2 3)
Command:!x
(1 2 3)
Command: ( type x )
LIST
СИМВОЛЫ
Command: ( setq x 'A )
A
Command:!x
A
Command: ( type a)
SYM
СТРОКИ
Текстовые строки могут иметь любую длину, до максимального объе-
ма памяти который может им выделяться. Их значение изменяется в
зависимости от количества кода AutoLISP и данных используемых в
настоящее время, и типа AutoLISP который используеися ( Обычный
или Расширенный ).
Строковые Константы ограничиваются максимальной длиной 100 симво-
лов.
Command: ( setq x " Text string " )
" Text string "
Command:!x
" Text string "
Command: ( type x )
STR
ВЕЩЕСТВЕННЫЕ ЧИСЛА
AutoLISP представляет вещественные числа как числа двойной точ-
ности с плавающей запятой, точные по крайней мере 14 значащими
цифрам. Нет никакого типа данных чтобы представить в AutoLISP
числа одиночной точности с плавающей запятой; все вещественные
числа - двойной точности, и представляются в AutoLISP тем же са-
мым способом каким они представляются в AutoCAD.
ТОЧНОСТЬ ОТОБРАЖЕНИЯ И ВНУТРЕННЯЯ ТОЧНОСТЬ
Точность отображения вещественных чисел в AutoLISP - только точ-
ность отображения. Внутреннее представление всегда точно по край-
ней мере до 14 цифр. Если необходимо отобразить или набрать зна-
чение вещественного числа с некоторой произвольной точностью вне
точности отображения AutoLISP-а по умолчанию, вещественное число
обычно преобразовывается в строку функцией AutoLISP (rtos) и
отображается или печатается в желаемой точности отображения.
(rtos) будет обсуждаться в будущем уроке о преобразовании типов
данных.
Command: ( setq x 4.5 )
4.5
Command:!x
4.5
Command: ( type x )
REAL
ЦЕЛЫЕ ЧИСЛА
В AutoCAD для DOS, целые числа - 16 битные числа со знаком в ин-
тервале между -32768 и +32767. Во всех других версиях AutoCAD,
они - 32 битные числа со знаком в интервале между -2,147,483,648
и +2,147,483,647. Целые числа перемещаемые между AutoLISP и
AutoCAD ограничиваются значениям в 16 бит. Для совместимости вер-
сий AutoCAD, лучше всего использовать в программах AutoLISP
только 16 битные значения.
Command: ( setq x 1 )
1
Command:!x
1
Command: ( type x )
INT
ОПИСАТЕЛИ ФАЙЛА
Описатель файла - внутренний указатель на файл, который открыт
для операции read/write/append. Функции желающие воздействовать
на открытый файл должны использовать описатель файла чтобы обра-
титься к файлу; следовательно, когда файл открывается, перемен-
ная должна связываться с описателем файла или файл не может быть
снова доступным.
В этом примере, функция (open) используется чтобы открыть файл
"file.ext" в каталоге и дисководе по умолчанию для операции запи-
си. Функция (open) возвращает описатель файла для "file.ext".
Command: ( setq x ( open "file.ext" "w" ))
Command:!x
Command: ( type x )
FILE
Command: ( setq x ( close x ))
nil
"ИМЕНА" ПРИМИТИВОВ AUTOCAD
Имя примитива - указатель на примитив в текущем сеансе редактора
AutoCAD. Имена примитивов изменяются от сеанса к сеанса, и то же
самое имя допустимо только в сеансе редактирования где оно найде-
но ( но оно будет допустимо для всего этого сеанса ).
Нет никакого способа сохранять имя примитива внутри рисунка
AutoCAD или внешнего файла для последующего использования в пос-
ледующих сеансах редактора; это средство преднамеренно недопусти-
мо.
Имена примитивов позволяют программам AutoLISP действовать на
уникальный, индивидуальный примитив. Методы выполняющие это бу-
дут исследоваться в следующих уроках; только краткий пример ил-
люстрируется здесь.
Функция (entlast) используемая в этом примере возвращает имя пос-
леднего примитива, добавляемого к рисунку.
Command: LINE
From point: 1,1
To point: 5,5
To point: return
Набор выбора - совокупность имен примиттивов, сохраненных во вре-
менном файле. Не более, чем шесть наборов выбора может открывать
AutoLISP в одно и тоже время. Для того, чтобы закрыть ненужную
переменную набора выбора, надо связывать переменную с нулем.
Функция (ssget) используемая в этом примере, запрашивает у
пользователя создать набор выбора и возвращает набор выбора как
значение выражения.
Command: LINE
From point: 1,1
To point: 5,5
To point: 10,1
To point: return
Command: ( setq x (ssget) )
Select objects: выбрать первую линию
Select objects: выбрать вторую линию
Select objects: return