Запис у файли
Для запису у файли термів і літер можуть бути використані в точності ті ж самі предикати, що обговорювалися раніше Єдина відмінність полягає в тому, що коли ми хочемо записати дані у файл, то нам потрібно змінити поточний вихідний потік даних так, щоб ним був файл, в який ми записуватимемо дані, а не дисплей терміналу. Поточний вихідний потік даних змінюється за допомогою предиката tell. Якщо X конкретизована ім'ям файлу, яке має бути атомом, то цільове твердження tell(X) перемикає поточний вихідний потік даних таким чином, що будь-яка операція запису (виконувана за допомогою write, put і інших подібних предикатів) проводитиметься в цей файл, а не на дисплей терміналу. Цільове твердження tell(X) можна погоджувати лише один раз. Так само при виконанні Прологом повернення за цільове затвердження tell не відбувається відновлення колишнього поточного вихідного потоку даних. Разом зі зміною поточного вихідного потоку даних предикат tell залежно від ситуації виконує також інші операції. Вперше, коли програма звертається до tell з конкретним ім'ям файлу X, Пролог вважає, що необхідно створити новий файл з цим ім'ям. Тому якщо X конкретизована деяким ім'ям файлу і файл з таким ім'ям вже існує, то усі літери, що вже містяться в цьому файлі, видаляються. Навпаки, якщо файлу з ім'ям, що є значенням X, не існує, то файл з таким ім'ям буде створений. У обох випадках файл вважається відкритим (для запису в нього). Це означає, що кожен подальший запис в цей файл додаватиме літери в кінець файлу до тих пір, поки не з'явиться явна вказівка, що запис у файл повністю завершений (поки файл не буде закритий). З цього моменту якщо буде зроблена нова спроба запису в цей файл, то Пролог, як і раніше, вважатиме, що необхідно писати в нову версію цього файлу. При спробі виконати tell(X), коли змінна X не має конкретного значення або її значення не є ім'ям файлу, виникає помилка. Реакція Пролог-системы на виникаючі помилки залежить від конкретної реалізації.
Предикат telling використовується для визначення імені файлу, що служить поточним вихідним потоком даних. Цільове твердження telling(X) вважається погодженим, якщо X має своїм значенням ім'я файлу поточного вихідного потоку даних. Як ви, напевно, здогадуєтеся, якщо X неконкретизована, то telling конкретизує X атомом (ім'ям файлу), що робить це цільове твердження вірним.
Коли запис у файл повністю завершений, то виконання предиката told оформить кінець файлу і закриє його (для виводу). Крім того, в результаті його виконання поточним вихідним потоком даних знову стане дисплей терміналу. Таким чином, типова послідовність цільових тверджень для запису у файл деякої сукупності літер має вигляд
... tell(іван), write(X), told, ...
Якщо поточний вихідний потік даних перемикається на інший файл без використання told, то колишній файл не буде закритий і залишиться доступним для запису в нього. Це дозволяє робити записи у файл з перервами, як в наступному прикладі:
...tell(X), write(A), tell(user), write(B), tell(X), write(C), told.
33.Читання файлів
Предикати, які надає Пролог для перемикання поточного вхідного потоку даних, аналогічні предикатам, що обговорювалися вище. Цільове твердження see(X) перемикає поточний вхідний потік даних на файл з вказаним ім'ям. Так само як і tell, це цільове твердження не може бути доведене знову, і виконана предикатом зміна вхідного потоку не переробляється при поверненні. При першому виконанні see(X) для деякого файлу X цей файл стає відкритим (для читання), при цьому читання починається з початку файлу. Подальша операція читання продовжує читати дані з того місця, де закінчила попередня операція. І так до тих пір, поки не буде зроблене явне закриття файлу. З цієї миті нова спроба читати з файлу приведе до того, що файл буде відкритий і читання почнеться з початку файлу, як і раніше. Поточний вхідний потік даних може бути означений в результаті виконання seeing(X), і поточний вхідний потік даних може бути перемкнутий назад на ввід з терміналу в результаті виконання цільового твердження seen, яке також закриває файл.
34.Ввід програм
Читання даних з файлів і запис даних у файли найбільш корисні тоді, коли об'єм даних, з якими працює наша програма і які ми хочемо помістити у базу даних, перевершує той об'єм, який ми можемо вводити вручну при кожному сеансі роботи з ЕОМ. У Пролозі файли використовуються головним чином для зберігання програм. Якщо текст Пролог-програми міститься в деякому файлі, то ми можемо прочитати всі твердження, що містяться у файлі, і помістити їх у базу даних, скориставшись для цього предикатом consult. Якщо значенням X є ім'я файлу, то мета consult(X) прочитає твердження (факти і правила) і цільові твердження з цього файлу. Більшість реалізацій Прологу мають спеціальну форму запису для предиката consult, що дозволяє прочитати послідовно один за одним список файлів. Якщо питання до Пролог-системи має вигляд списку атомів, то Пролог-система прочитає кожен файл з цього списку. Як приклад використання такої форми запису приведемо наступне запитання:
?— файл1, відображення, експерт.
Це питання обробляється таким чином, начебто Пролог виконував цільове твердження consultall(X), де X — це список, що заданий в запитанні, а предикат consultall означений таким чином:
consultall([]).
consultall(H|T]) :- consult(H), consultall(T).
Проте короткий списковий запис економічніший, а це особливо важливо, якщо взяти до уваги, що найперша дія, яку виконує працюючий з Прологом програміст,— це читання з файлів своїх предикатів. Предикат consult автоматично припиняє читання тверджень, коли зустрічається кінець файлу. У питанні 1 теми 6 предикат consult описується детальніше.
35.Оголошення операторів
Оператори надають деякі синтаксичні зручності при читанні і записі термів. Синтаксис мови дозволяє використання операторів, що мають наступні три властивості: позицію, пріоритет і асоціативність. По займаній позиції оператори можуть бути інфіксними, постфіксними або префіксними (оператор, що має два аргументи, може розташовуватися між аргументами; оператор з одним аргументом може знаходитися або після аргументу, або перед ним). Пріоритет оператора — це деяке ціле число, діапазон зміни якого залежить від конкретної реалізації Прологу. Припустимо, що воно знаходиться в діапазоні від 1 до 255. Пріоритет використовується для того, щоб надати однозначну інтерпретацію виразам в тих випадках, коли синтаксис термів не заданий явно за допомогою дужок. Асоціативність потрібна для надання однозначної інтерпретації виразам, в яких є два оператори з однаковими пріоритетами.
Для інфіксних операторів можливі наступні специфікації:
xfx xfy yfx yfy
Буква f представляє оператор, а х і у — аргументи. Оператор має бути між аргументами.
Префіксні:
fx fy
оператор записується перед його єдиним аргументом.
Постфіксні:
xf yf
yfx, є лівоасоціативним. Аналогічно оператор із специфікацією xfy є правоасоціативним.
Якщо ми хочемо оголосити на Пролозі оператор із заданими позицією, пріоритетом і асоціативністю так, щоб Пролог розпізнавав його при вводі і виводі термів, то ми використовуємо вбудований предикат ор. Оператор може бути оголошений за допомогою виконання наступного цільового твердження
?— ор(Пріоритет, Специфікація, Ім'я).
Якщо оголошення оператора є допустимим, то ця мета буде досягнута.
?—op(255, xfx, ':-').
?—op(255, fx, '?-').
?—op(254, xfy, '; ').
?—op(253, xfy, ',').
?—op(250, fx, spy).
?—op(250, fx, nospy).
?—op(60, fx, not).
?—op(51, xfy, '.').
?—op(40, xfx, is).
?—op(40, xfx,' =..')
?—op(40, xfx, =).
?—op(40, xfx,\=).
?—op(40, xfx,<).
?—op(40, xfx, =<).
?—op(40, xfx,>=).
?—op(40, xfx,>).
?—op(40, xfx, = =).
?—op(40, xfx,\ = =).
?—op(31, yfx,-).
?—op(31, yfx,+).
?—op(21, yfx,/).
?—op(21, yfx,*).
?—op(ll, xfx, mod).