Главная Случайная страница


Полезное:

Как сделать разговор полезным и приятным Как сделать объемную звезду своими руками Как сделать то, что делать не хочется? Как сделать погремушку Как сделать так чтобы женщины сами знакомились с вами Как сделать идею коммерческой Как сделать хорошую растяжку ног? Как сделать наш разум здоровым? Как сделать, чтобы люди обманывали меньше Вопрос 4. Как сделать так, чтобы вас уважали и ценили? Как сделать лучше себе и другим людям Как сделать свидание интересным?


Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Управляющие конструкции Автолиспа - ветвление





 

Поскольку список - главное действующее лицо языка Лисп, следует тщательно рассмотреть набор функций по работе с ними.

До некоторой степени список аналогичен массиву в языках типа Паскаля. Там доступ к конкретному элементу списка решается просто - указывается его номер: a[5]. В Лиспе все несколько сложнее.

Функция (CAR l) возвращает первый элемент списка l.

Например, (CAR (LIST 10 20)) вернет 10.

Если список l является описанием координат точки, то (CAR l) возвращает координату X.

Функция (CADR l) возвращает все элементы списка l, кроме первого. Иначе говоря, у списка отрывается "голова", а возвращается остающийся "хвост", причем даже если этот "хвост" длиной в один атом, он все равно будет списком:

(CDR (LIST 10 20)) возвращает (20)

Функция CDR не годится для получения координаты Y точки - она возвращает список, а координата, конечно же, должна быть выражена атомом - вещественным числом. По-хорошему надо из списка, возвращаемого функцией CDR, выделить первый элемент, написав

(SETQ p (LIST 10 20)); координаты точки p

(SETQ y (CAR (CDR p)))

Но такая запись выглядит весьма громоздко. Поэтому в Лиспе предусмотрена возможность использования вложенных функций CAR и CDR, которые будут называться соответственно CADR, CDAR, CAAR, CDDR и так далее (до четырех уровней вложенности). При этом (CADR l) эквивалента (CAR (CDR l)).

Последний элемент списка как атом возвращает функция (LAST l). В принципе ее можно использовать для получения координаты Y, но где гарантия, что в один прекрасный день пользователь не включит режим использования трехмерных точек? Тогда LAST станет возвращать уже координату Z и ваша программа тут же потеряет работоспособность.

И, наконец, самая общая функция выделения элементов из списка: (NTH n l), которая возвращает n-й элемент списка l.

Нумерация элементов списка в функции NTH начинается с нуля!

Итак, поскольку наиболее часто нам нужно выделить отдельные координаты точки, подытожим, как это легче всего сделать:

 

Таблица - Получение координат точек.

Точка p
Координата Х Координата Y
(CAR p) (CADR p)
(NTH 0 p) (NTH 1 p)

 
 

Разбор точек на координаты используется, если необходимо рассчитать положение точки через приращения. Например, при отрисовке фаски нужно узнать координаты точки P2, зная точку P1:

 

Рисунок Отрисовка фаски.

Хотя угол здесь задан в явном виде, использование функции POLAR будет некорректным: мы не знаем расстояние P1P2.

Если его высчитывать как гипотенузу прямоугольного треугольника, точность вычисления квадратного корня окажется ограниченной и мы не попадем в точку P2. Если бы мы рисовали фаску вручную, то мы бы ввели приращения по осям в виде @3,3 (т.е. переместиться от точки P1 вправо на 3мм и верх на 3 мм). Сделаем то же самое в Автолиспе:

(SETQ p2 (LIST (+ (CAR p1) 3)

(+ (CADR p1) 3)))

Такая запись является стандартным способом расчета координат точек в приращениях.

При использовании списков, особенно списков-данных, часто необходимо добавлять в имеющийся список новые и новые значения, как бы "приклеивая" их к его хвосту. Для этого предназначена функция (APPEND l1 l2), которая добавляет в конец списка l1 список l2 и возвращает новый, удлиненный список. Список l1 от этого автоматически не меняется, нужно сохранять результат выполнения функции APPEND.

Обратите внимание: для добавления в список атома его сначала нужно превратить список из одного элемента!

Пример: в переменной а хранится список вида (19 49). К нему нужно добавить число 20. Делается это так:

(SETQ a (APPEND a (LIST 20)))

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

И ветвление, и цикл в обязательном порядке содержат проверку условия. В качестве условий в Лиспе используются логические функции, возвращающие T (true - истина) или NIL (ложь): "<", ">", "<=", ">=", "=", "/=". Обратите внимание: операция "не равно" записывается не так, как в большинстве других языков программирования!

Функции сравнения могут применяться к целым и вещественным числам, а также текстовым строкам, но не к спискам.

Примеры:

(= 2 2) возвращает T

(= 2 5) возвращает NIL

(= "ABC" "AB") возвращает NIL

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

(SETQ a1 (SIN 0.0))

(SETQ a2 (SIN (* 2.0 PI)))

Тогда (= a1 a2) возвращает NIL, т.е. с точки зрения Лиспа , поскольку не равен точно нулю.

Что же делать, если нужно сравнить два вещественных числа, когда хотя бы одно из них - результат вычисления тригонометрической или иной функции? (заметим, что аналогичная проблема в других языках программирования просто обходится молчанием). Создатели Лиспа ввели в язык специальную функцию сравнения с заданной точностью:

(EQUAL e1 e2 точность)

Здесь точность - число (0.1, 0.01..), указывающее, сколько знаков поле запятой принимается во внимание при сравнении выражений e1 и e2. Поэтому функция (EQUAL (SIN 0)(SIN (* PI 2)) 0.1) вернет T.

Функции сравнения могут объединяться при помощи логических функций, образуя сложные условия. В Лиспе имеется богатый набор логических функций (заметно больший, чем в других языках), из которых реально достаточно знать следующие четыре:

 

Таблица - Логические функции языка Автолисп.

X Y X AND Y X OR Y X XOR Y NOT X
T NIL NIL T T NIL
T T T T NIL NIL
NIL T NIL T T T
NIL NIL NIL NIL NIL T

 

Теперь мы готовы к рассмотрению функции IF, обеспечивающей ветвление в программе. Ее общий вид:

(IF c

f1

[f2]

)

 

Здесь с - условие (простое или сложное):, f1 - функция, выполняемая, если условие истинно (часть "то"), а f2 - функция, выполняемая, когда условие ложно (часть "иначе"), причем квадратные скобки говорят о том, что часть "иначе" может отсутствовать.

_&_ Простейший пример:

 

(IF (< a 0)

(PROMPT "\nПеременная a меньше нуля")

(PROMPT "\n"Переменная a больше или рана нулю"))

А как быть, если нужно в случае выполнения (или невыполнения) условия выполнить не одну, а сразу несколько функций? Ведь синтаксис функции IF разрешает записать только одну. Проблема решается так же, как в языке Паскаль: там используются операторные скобки begin..end, а в Лиспе - функция (PROGN f1 f2.. fn). Она всего лишь объединяет функции f1 f2.. fn в один блок, который можно подставить в функцию IF.

Например, мы решаем квадратное уравнение и в переменную d записали дискриминант. Теперь нужно посчитать действительные корни и вывести их на экран:

(IF (>= d 0)

(PROGN

(SETQ x1 (/ (+ (* b -1) (SQRT d))

(* 2 a))

(SETQ x2 (/ (- (* b -1) (SQRT d))

(* 2 a))

(PROMPT "\nX1=")

(PRINT x1)

(PROMPT "\nX2=")

(PRINT x2)

); конец PROGN

(PROMPT "\nДействительных корней нет"); "иначе"

)

Продолжая рассматривать параллели с Паскалем, обратимся к функции COND, обеспечивающей множественное ветвление аналогично паскалевскому оператору CASE. Ее общий вид:

(COND

(c1 f11 f12... f1n1)

(c2 f21 f22... f2n1)

...

(cm fm1 fm2... fmnm)

)

Здесь с1..cm - логические условия, fnm - функции, выполняемые при выполнении того или иного условия.

Основное назначение функции COND - обработка ввода пользователя, например, так:

 

(SETQ a (GETINT "\n1 - фаска, 2 - галтель, 3 - выточка"))

(COND

((= a 1)....); фаска

((= a 2)....); галтель

((= a 3)....); выточка

)

 

Date: 2015-12-12; view: 387; Нарушение авторских прав; Помощь в написании работы --> СЮДА...



mydocx.ru - 2015-2024 year. (0.006 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию