- •1. Введение в декларативные языки.
- •Прозрачность по ссылкам.
- •Логическое программирование
- •Правила
- •Примеры
- •Рекурсивные определения
- •Литература
- •Синтаксис пролога.
- •Структуры
- •Предикаты
- •Семантика пролога
- •Как происходит сопоставление
- •Алгоритм Эрбрана
- •Алгоритм вычисления целей(работы пролог машины).
- •Процедурный смысл правил
- •Использование списков и
- •Использование накапливающего параметра(прием)
- •Операторная запись
- •Управление перебором
- •Алгоритмы сортировки
- •1 Пузырьковая сортировка
- •Сортировка вставками
- •Быстрая сортировка.
- •Использование предикатов, анализирующих типы или структуру термов
- •Применение подстановки к структурированному терму
- •Недетерминированное программирование
- •Метод «породить и проверить»
- •Алгоритм сортировки
- •Программирование второго порядка
- •Рассмотрим, как работать с базой данный
- •Поиск в глубину
- •Темы кр
- •Использование формальных языков
- •Недетерминированный конечный автомат
- •Ввод и вывод
- •Рассмотрим ввод вывод алфавитно – цифровых символов
- •Функциональное программирование
- •Базовый язык
- •Рекурсивное определение функций
- •Функции высших порядков
- •Отображение списков
- •Декартово произведение множеств
- •Композиция функций.
- •Бесконечные списки
- •Рассмотрим как можно исп беск списки.
- •Метод породить и проверить
- •Сети связанных процессов
- •Определение ф чисел фибоначи
- •Задача хэмминга
- •Решето Эратосфена
- •Язык типов
- •Рассмотрим алгебраические типы данных.
- •Деревья – рекурсивные типы данных
- •Сделать дерево плоским
- •Удаление элемента дерева
- •Извлечение самого правого элемента
- •Функция форматирования числа
- •Законы функциональных программ
- •Наиболее важные законы функц программ доказываются по индукции
- •Закон map через foldr
- •Закон: композиция
- •Коммутативна
- •Дистрибутивность map относительно композиции:
- •Преобразование программ
- •Пример1
- •Стратегия для композиции
- •Приведение рекурсивной формы к итеративной форме
- •Введение в лямбда исчисление
- •Синтаксис лямбда исчисления
- •Множество связанных переменных
- •Множество свободных переменных
- •Подстановка
- •Конфликт имен(захват переменных)
- •Преобразование термов
- •Вторая теорема Черча – Россера “Теорема о стандартизации”
- •Комбинатор y
- •Вычислим fact 3
- •Вычислим fact 0
- •(Рассказ про y комбинатор – сразу зачёт)
Ввод и вывод
До сих пор мы рассматривали программы котторые работали в режиме вопрос ответ. В прологе есть встроенные предикаты, которые могут обращаться к у ввода вывода. Такие предикаты имеют побочный эффект они еще изменяют состояние буфера устройства ввода вывода. Правда они нарушают логии модель пролога.
Входные потоки
Входные файлы
Выходные потоки
Вых файлы
э
терминал
Программа на прологе
файлы
user
Потоки, связанные с файлами обозначаются именами этих файлов.
В каждый момент работы программы может быть активным один поток ввода и один поток вывода.
Нельзя несколько потоков сразу….и из них…
Предикат see /1 определяет текущий поток ввода.
А tell /1 поток вывода.
Закрыть файлы можно предикатами
seen /0
told /0
что касается ввода вывода есть 2 режима, режим ввода термов, режим ввода вывода отдельных символов.
Теперь об обработке термов
Предикат read /1 вызывает чтение из текущего входного потока терма
?- read(T).
Будет прочитан терм и связан с переменной T. Терм может быть любой сложности.
Аргумент предиката read и входные данные долдны быть сопоставимы. Унификация тут используется.
?- read(pnt(X,Y)).
Если предикат read потерпит неудачу, то старое состояние буфера не восстанавливается.
write /1.
Любой терм может быть выведен в выходной поток.
Рассмотрим пример ввода данных.
Рассмотрим как можно ввести последовательность термов.
vhod
See open
Seen close
Tell told for vivod!.
Нужно открыть файл
?-see(‘d:\work\data.txt’), rd_lst(X), seen, see(user), write(X).
rd_lst(X) вводит все термы, которые есть в файле.
rd_lst(Ts):-
read(T),
rd_next(T,Ts).
Прочитали терм и посмотрели нет ли конца файла. Это делает rd_next.
rd_next имеет 2 варианта. Если при чтении конец файла то прочитанный терм будет атомом end_of_file
rd _next(end_of_file, []).
rd _next(T, [T|Ts]):- rd_lst(Ts).
Рассмотрим ввод вывод алфавитно – цифровых символов
Символы задаются числами от 0 до 127 в кодировке ASCII.
Предикат put /1 выводит один символ в выходной поток.
?- put(65).
A
Yes
Можно исп сам символ в кавычках.
?- put(“?”).
?
Yes
Кавычки могут быть как одинарные, так и двойные.
Для ввода есть 2 основных предиката get0 /1. Этот предикат читает символ из входного потока.
Предикат get /1 читает первый входной символ, имеющий графическое изображение.
Он игнорирует табуляцию, пробелы, …
Когда вводится последовательность символов нам нужно из них строить атомы и или числа.
Для этого есть предикат name /2, который ставит в соответствие атому или числу список символов.
?- name(X, [‘a’,’b’]).
X = ab
То же самое можно и числами.
Рассмотрим программу которая читает посимвольно список и преоб его в прологовские термы.
getLx(R):-
get0(Ch),
( Ch = 46 -> % если точка то…
R = [];
getLx(Rt),
R = [Ch|Rt]).
digit(D) --> [D], {between(48,57,D)}. % 0..9
letter(L) --> [L], {between(97,122,L)}. %a..z
num([D|Ds]) -->digit(D), num(Ds).
num([D])--> digit(D).
p :- b,:,e1.
p:- e2.
Этот предикат p можно рассматривать как условие if b then e1 else e2.
Есть синтаксическое расширение для этой конструкции след вида:
( b-> e1; e2)
b, e1, e2 – любые последовательности целей.
определим 2 синтаксические категории цифры и буквы
digit терм D, D переменная, она имеет дополнит условие ( в фиг скобах дополнительный предикат) что она в диапазоне…48…57…
сам предикат digit имеет дополнительный параметр, распознанная цифра.
letter аналогично.
Нетерминал имеет параметр L.
После этого можно определить число. Число – это цифра за которой следует число и одна цифра.
Здесь мы исп дополнительные параметры. Число имеет дополнит параметр – список из цифр. этот список будет результатом трансляции. Эти обозначения соответствуют атрибутной грамматике.
Пример
% как исп num
% ?- getLx(X), num(Y,X,[]).
|: 123.
% X = Y, Y = [49, 50, 51].
% ?- getLx(X), num(Y,X,[]).
% |:12q.
% False.
Правые 2 параметра это входная последовательность . далее дополн параметры . тут это Y. далее оператор ввел 123, пролог выдал ответ … X = Y, Y = [49, 50, 51].
Рассмотрим как определить идентификатор
Идентификатор – последовательность букв или цифр, начинающихся с буквы.
Id([L|LDs]) --> letter(L), lod(LDs).
lod([L|LDs]) --> letter(L), lod(LDs).
lod([D|LDs]) --> digit(D), lod(LDs).
lod([]) --> [].
lpar --> [40]. %левая круглая скобка
rpar --> [41]. %пр
space --> [32]. % пробел
delim --> space, delim. % разделитель, 1 или более пробелов
delim --> space.
Пример
Elem – элемент списка
Id –список символов, обознач идентфиикатор
elem(Ida) --> id(Id), {name(Ida,Id)}.
elem(Nt) --> num(N), {name(Nt,N)}.
elem(L) --> list(L).
list(L) --> lpar, elem(L), rpar.
elems([H|T]) --> elem(H), delim, elems(T).
elems(A) --> elem(A).
elems([]) --> [].
?- getdx(X), list(Y, X,[]).
|: (let ((x 12) (y 13)) (add x y)).% контсрукция на Лиспе. Наша программа разберет его как список Лисп….
Y = [let, [[x,12], [y, 13]], [add, x, y]].
Сложные структуры можно так разобрать, расписать.