Опубликован: 12.02.2014 | Доступ: свободный | Студентов: 818 / 236 | Длительность: 11:22:00
Специальности: Программист
Лекция 12:

Язык запросов

Аннотация: Настоящая глава посвящена созданию базы данных "Родственные отношения". База может изменяться во время исполнения программы, с помощью добавления и удаления фактов, в процессе диалога с пользователем. Рассматривается язык запросов к базе данных, близкий к естественному языку. Вычисляются ответы на запросы. Создается консольный проект в объектном стиле.

Настоящая глава посвящена созданию базы данных "Родственные отношения". База может изменяться во время исполнения программы, с помощью добавления и удаления фактов, в процессе диалога с пользователем. Рассматривается язык запросов к базе данных, близкий к естественному языку. Вычисляются ответы на запросы.

В данной главе создается консольный проект в объектном стиле.

Язык Visual Prolog — объектно-ориентированный. Классы и интерфейсы создаются с помощью диалогового окна Create Project Item. Классы могут иметь интерфейс, а могут не иметь интерфейса. Объекты порождают те, и только те классы, которые имеют интерфейс.

Декларация класса помещается в файл с расширением cl, интерфейс — в файл с расширением i, имплементация — в файл с расширением pro.

Рассмотрим пример интерфейса, декларации класса с этим интерфейсом и его имплементации.

interface person      % интерфейс
    open core

    properties
        id : unsigned.
        name : string.
        age : positive.
end interface person
%---------------------------------------------------------------------------
class person : person      % декларация класса
    open core

    constructors        % объявление конструктора
        new: (unsigned Id).

    predicates
        count: () -> positive.
end class student
%---------------------------------------------------------------------------
implement person        % имплементация класса
    open core

    facts
        id : unsigned.
        name : string := "".
        age : positive := 18.
    
    class facts
        counter : positive := 0.

    clauses
        new(Id):-
            id := Id,
            counter := counter + 1.

        count() = counter.
end implement person
%---------------------------------------------------------------------------
goal            % цель программы
    mainExe::run(main::run),
    P1 = person::new(1),
    P1:name := "Вася",
    P1:age := 18,
    P2 = person::new(2),
    P2:name := "Маша",
    P2:age := 19,
    stdio::writef("%. % - %\n%. % - %\nКоличество = %",
        P1:id, P1:name, P1:age, P2:id, P2:name, P2:age,
        person::count()).
Пример 12.1. Класс person с интерфейсом person

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

facts
    n: positive.
clauses
    age() = n:-
        stdio::writef("Считано значение свойства age = %\n", n).
    age(V):-
        n := V,
        stdio::writef("Свойству age присвоено значение %\n", n).

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

Конструкторы классов возвращают указатели на объекты этих классов, хотя объявляются и определяются в виде обычных предикатов. Для того чтобы вызвать метод объекта, следует написать имя переменной, хранящей указатель на объект, затем поставить знак двоеточия. После этого, как обычно, пишется свойство или имя предиката и его аргументы.

Подробнее об объектно-ориентированном программировании в языке Visual Prolog см. [17].

12.1. База данных

Данный параграф посвящен созданию базы данных (как обычно, вначале следует создать консольный проект).

Для реализации доступа к сведениям, хранящимся в базе данных, создается класс dbrel. Объект базы данных создается по имени файла, в котором хранятся факты базы данных.

В базе данных хранятся сведения об именах и фамилиях людей, их поле, отце, матери и супругах. Каждый человек имеет уникальный идентификатор. При записи сведений о новом человеке ему автоматически присваивается идентификатор. Для хранения записей используется два отношения — person/6 и spouse/2.

Ниже приведен интерфейс общения с базой данных (файл dbrel.i).

constants
    male = "м".
    female = "ж".

predicates
    load: ().
    save: ().
    person_nd: (unsigned, string, string, string, unsigned, unsigned)
        nondeterm (o,o,o,o,o,o) (o,i,o,o,o,o) (o,i,i,o,o,o) (o,o,o,i,o,o)
           (o,o,o,o,i,o) (i,o,o,o,o,o) (i,o,o,o,i,o) (o,o,o,o,o,i) (i,o,o,o,o,i).
    spouse_nd: (unsigned, unsigned) nondeterm (o,o) (i,o) (o,i).
    getSex: (unsigned Id) -> string determ.
    getNewId: () -> unsigned.
    setPerson: (unsigned, string, string, string, unsigned, unsigned).
    setSpouse: (unsigned, unsigned).
    delPerson: (unsigned).
    delSpouse: (unsigned, unsigned).
Пример 12.2. Интерфейс dbrel

Конструктор объявляется так, как показано ниже (файл dbrel.cl).

constructors
    new: (string FileName).
Пример 12.3. Декларация класса dbrel

Имплементация приведена в листинге 12.4 (файл dbrel.pro).

facts
    filename : string.
    maxId : unsigned := 0.
clauses
    new(FileName):-
        filename := FileName.

facts - rel
    person: (unsigned, string, string, string, unsigned, unsigned).
    spouse: (unsigned IdHusband, unsigned IdWife).

clauses
    load():-
        try file::consult(filename, rel)
        catch Error do
            writef("Error %. Unable to load the database from "
                "the file %\n", Error, filename)
        end try,
        setMaxId().
        
    save():-
        file::save(filename, rel),
        write("\nИзменения сохранены в базы данных.").

    person_nd(Id, Name, Surname, Sex, IdF, IdM):-
        person(Id, Name, Surname, Sex, IdF, IdM).

    spouse_nd(IdH, IdW):-
        spouse(IdH, IdW).

    getSex(Id) = Sex:-
        person(Id, _, _, Sex, _, _),
        !.

    getNewId() = maxId:-
        maxId := maxId + 1.

    setPerson(Id, Name, Surname, Sex, IdF, IdM):-
        assert(person(Id, Name, Surname, Sex, IdF, IdM)),
        writef("Запись '% - % - % - % - % - %' добавлена\n",
            Id, Name, Surname, Sex, IdF, IdM).

    setSpouse(IdH, IdW):-
        assert(spouse(IdH, IdW)),
        writef("Запись '% - %' добавлена\n", IdH, IdW).

    delPerson(Id):-
        retractAll(person(Id, _, _, _, _, _)),
        writef("Записи о % удалены\n", Id).

    delSpouse(IdH, IdW):-
        retractAll(spouse(IdH, IdW)),
        writef("Запись '% - %' удалена\n", IdH, IdW).

predicates
    setMaxId: ().
clauses
    setMaxId():-
        L = [Id || person(Id, _, _, _, _, _)],
        L <> [],
        !,
        maxId := list::maximum(L).
    setMaxId().
Пример 12.4. Имплементация класса dbrel
Жаныл Айкын
Жаныл Айкын
Rustam Inatov
Rustam Inatov

Доброго времени суток, подскажите пожалуйста, visual prolog examples, pie, vip7.5 - это все, где я могу скачать? (в смысле) может быть на сайте есть какой-то архив? Увы я не нашел его.

Подскажите, пожалуйста.

С уважением, Рустам.