## ЛЕКЦИЯ 4.

Логические функции. Управляющие структуры. Простые функции печати. PROGN.

Содержание

  4.1 MEMBER.
  4.2 Логические функции.
  4.2.1 NOT.
  4.2.2 OR.
  4.2.3 AND.
  4.3 Управляющие структуры.
  4.3.1 COND.
  4.3.2 Другие условные предложения.
  4.3.3 Связь между COND и логическими функциями.
  4.4 Ввод и вывод информации.
  4.4.1 READ.
  4.4.2 PRINT.
  4.5 PROGN, PROGN1, PROGN2.
  4.5.1 Определение функций с использованием неявного PROGN.

## 4.1 MEMBER.

Функция проверяет, находится ли первый аргумент внутри списка, представленного вторым аргументом.
Если элемента в списке нет, MEMBER возвращает nil.

Функция MEMBER имеет два аргумента:

- Первый аргумент - это s-выражение,
- Второй - обязательно список.

### ( MEMBER < s-выражение > < список > )

* ( member ' b ' ( c d b a ) )
( b a )

Если элемент в списке есть, то MEMBER возвращает хвост второго аргумента, начинающийся с этого элемента.

Таким образом member в качестве истины возвращает не Т , а величину не-NIL.
В Лиспе для предикатов значение не-NIL означает истину.

* ( member ' с ' ( a b ( c ) ) )
NIL

Т.к. элемент находится
не на том уровне.

## 4.2 Логические функции.

Для объединения предикатов в сложные выражения и для выделения элементов - NIL в Лиспе используются логические функции AND , OR и NOT .

## 4.2.1 NOT.

Функция NOT берет один аргумент и возвращает значение, противоположное значению аргумента. Если аргумент NIL,
NOT возвращает Т. Если аргумент любое значение не-NIL,
NOT возвращает NIL.

NOT имеет один аргумент, который может быть
любым s-выражением (не только предикатом).

### ( NOT < s-выражение >)

Примеры:

* ( not ( zerop 1 ) )
T

* ( not nil )
T

* ( not ' ( a b c ) )
NIL

## 4.2.2 OR.

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

В OR , аналогично NOT, аргументами могут быть любые выражения.

### ( OR < arg-1 >< arg-2 >< arg-3 > . . . )

Примеры:

* ( or t nil )
T

* ( or nil nil )
NIL

* ( or ( atom 1) ( > 3 4 ) '( a b c ) ) )
( a b c )

Таким образом:

- OR возвращает значение не-NIL, если по крайней мере один аргумент не NIL.
- OR используется для выделения первого не пустого элемента в списке.

## 4.2.3 AND.

Логическая функция AND берет один или несколько аргументов. Она выполняет эти аргументы слева направо. Если она встречает аргумент, значение которого NIL, она возвращает NIL, не продолжая вычисления остальных. Если NIL аргументов не встретилось, то возвращается значение последнего аргумента.

### ( AND < arg-1 >< arg-2 >< arg-3 > . . . )

Примеры:

* ( and 5 nil )
NIL

* ( and ' a ' b )
b

* ( and ( listp nil ) ( atom nil ) )
T

Таким образом:

- AND возвращает NIL значение, если хотя бы один из аргументов NIL, в противном случае возвращается значение последнего аргумента.

- AND используется для выделения пустого элемента в списке.

## 4.3 Управляющие структуры.

В обычных языках программирования существуют средства управления вычислительным процессом: организация разветвлений и циклов. В Лиспе для этих целей используются управляющие структуры - предложения (clause). | Внешне предложения записываются как вызовы функций: Первый элемент предложения - имя; остальные - аргументы. В результате вычисления предложения получается значение. Отличие от вызова функции в использовании аргументов.

Управляющие структуры делятся на группы. Одна из групп - разветвления вычислений.

В нее входят:

- условные предложения:

COND IF WHEN UNLESS

## 4.3.1 COND.

Предложение СOND является основным средством организации разветвления вычислений.

Структура условного предложения :

### ( COND ( < проверка-1 > < действие-1 > )
( < проверка-2 > < действие-2 > )
...............................................................
( < проверка-n > < действие-n > ))

В качестве аргументов < проверка > и < действие > могут быть произвольные формы.

Значение COND определяется следующим образом:

- Выражения < проверка-i >, выполняющие роль предикатов вычисляются последовательно, слева направо, до тех пор, пока не встретится выражение, значением которого не является NIL.

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

- Если истинного значения нет, то значением COND
  будет NIL.

Обычно в качестве последнего условия пишется t, соответствующее ему выражение будет вычислятся в тех случаях, когда ни одно другое условие не выполняется.

Последнюю строку можно записать: ( t ' atom ) ) )

Пример: ( функция проверяет тип аргумента)

( defun classify ( arg )

( cond
( ( null arg ) nil )
( ( list arg ) 'list )
( ( numberp arg ) 'number )
( t 'atom ) )

* ( classify 'a )
atom

* ( classify 5 )
number

Еще один пример:

( defun double1 ( num )

( cond
( ( numberp num ) ( * num 2 )
( t ' не-число ) )

Эта функция
гарантировано удваивает
число, отбрасывая
не числовые аргументы.

В COND могут отсутствовать результирующие выражения для предикатов, а так же присутствовать несколько действий.

### ( COND
( < проверка-1 > )
( < проверка-2 > < действие-2 > )
(< проверка-3 > < дейст.-31 > < дейст.-32 > < дейст.-33 >))

- Если нет действия - результат значение предиката.

- Если не одно действие - результат значение последнего аргумента.

## 4.3.2 Другие условные предложения.

СOND наиболее общее условное предложение. Часто пользуются более простыми условными предложениями.

### ( IF < условие > < то форма > < иначе форма > )

Пример:

( if ( atom x ) 'аtоm 'not - аtom )

Условные предложения WHEN и UNLESS являются часными случаями условного предложения IF:

- Если условие соблюдается, то выполняются формы.

  ### ( WHEN < условие >
  < форма-1 > < форма-2 > < форма-3 > ... )

- Если условие не соблюдается, то выполняются формы.

  ### ( UNLESS < условие >
  < форма-1 > < форма-2 > < форма-3 > ... )

## 4.3.3 Связь между COND и логическими функциями.

Любую логическую функцию можно заменить COND-выражением и наоборот.
Пример:

car-функция с проверкой:

( defun gcar ( l )
( cond
( ( listp l ) ( car l ) )
( t nil ) ) )

то же через логические функции:

( defun gcar1 ( l )

( and
( listp l ) ( car l ) ) )

* (gcar '(a b))

a

* (gcar 'a)

nil

## 4.4 Ввод и вывод информации.

До сих пор в определяемых функциях ввод и вывод результатов осуществлялись в процессе диалога с интерпретатором. Интерпретатор читал вводимое пользователем выражение, вычислял его значение и возвращал его пользователю. Теперь мы рассмотрим специальные функции ввода и вывода Лиспа.

## 4.4.1 READ.

READ отличается от операторов ввода-вывода других языков пpогpаммиpования, тем что он обрабатывает вводимое выражение целиком, а не одиночные элементы данных.

Вызов функции осуществляется в виде:

### ( READ )

функция без аргументов.

Как только интерпретатор встречает READ, вычисления приостанавливаются до тех пор пока пользователь не введет какой-либо символ или выражение.

* ( READ )
new -

выражение пользователя
new - значение функции.

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

* ( setq x ' ( read ) )

( + 1 2 )

- вводимое выражение

( + 1 2 )

- значение

* x
( + 1 2 )

* ( eval x )
3

Еще один пример:

( defun tr ( arg )
( list ( + arg ( read ) ) ( read ) ) )

* ( tr 8 )
14
cat
( 22 cat)

## 4.4.2 PRINT.

Функция PRINT - это функция с одним аргументом. Она выводит значение аргумента на монитор, а затем возвращает значение аргумента.

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

### ( PRINT < arg >)

print перед выводом аргумента переходит на новую строку,
а после него выводит пробел.

* ( print ( + 2 3 ) )

5 -

вывод
5 - значение

print и read - псевдофункции, у которых кроме значения есть побочный эффект.
Значение функции - значение ее аргумента.
Побочный эффект - печать этого значения.

Это не значит, что всегда две строки. Только когда print на высшем уровне, чего практически не бывает.

Пример:

* ( setq row ' ( x x x ) )
( x x x )

* ( print ( cdr row ) )
( x x ) -

печать
( x x ) - значение

* ( cons 'o ( print ( cdr row ) ) )
( x x ) -

печать
( o x x ) - значение

## 4.5 PROGN, PROG1, PROG2.

Функции PROGN, PROG1, PROG2 относятся к управляющим структурам, к группе объединяющей последовательные вычисления.

Предложения PROGN, PROG1, PROG2 позволяют работать с несколькими вычисляемыми формами:

### ( PROGN < форма-1 > < форма-2 > ...... < форма-n >)
( PROG1 < форма-1 > < форма-2 > ...... < форма-n >)
( PROG2 < форма-1 > < форма-2 > ...... < форма-n >)

У этих предложений переменное число аргументов, которые они последовательно вычисляют:

Пример:

* ( progn ( setq x 2 ) ( setq y ( * 3 2 ) ) )
6

* ( prog1 ( setq x 2 ) ( setq y ( * 3 2 ) ) )
2

* y
6

В Лиспе часто используется так называемый неявный PROGN , т.е вычисляется последовательность форм, а в качестве значения берется значение последней формы.

## 4.5.1 Определение функций с использованием неявного PROGN.

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

### ( defun
< имя функции >
< список параметров >
< форма1 форма2 .... формаN > )

- Тело функции состоит из последовательности форм отражающих,
  последовательность действий.
- В качестве значения функции принимается значение последней формы.

Пример:
Определим функцию, которая печатает список, вводит два числа, и печатает их сумму.

( defun print-sum ( )

; функция без аргументов
( print ' ( type two number ) )
( print ( + ( read ) ( read ) ) ) )

*( print-sum )
( type two number ) 3 4
7
7

Содержание