Prolog
Шрифт:
F = 2*t*f( t)
Под "вхождением" Подтерм'а в Терм мы будем понимать такой элемент Терм'а, который сопоставим с Подтерм'ом. Вхождения будем искать сверху вниз. Поэтому цель
?- подставить( а+b, f( а, А+В), v, F).
даст результат
F = f( а, v) F = f( a, v+v)
А =
В = b В = а+b
При определении отношения подставить нам нужно рассмотреть несколько случаев и для каждого принять свое решение:
если Подтерм = Терм, то Терм1 = Подтерм1;
иначе если Терм– "атомарный" (не структура),
то Терм1 = Терм (подставлять нечего),
иначе подстановку нужно выполнить над
аргументами Tерм'a.
Эти правила можно превратить в программу, показанную на рис. 7.3.
Термы, полученные при помощи предиката '=..', разумеется, можно использовать и в качестве целей. Это дает возможность программе в процессе вычислений самой порождать и вычислять цели, структура которых не обязательно была известна заранее в момент написания программы. Последовательность целей, иллюстрирующая этот прием, могла бы выглядеть примерно так:
получить( Функтор),
вычислить( Списарг),
Цель =.. [Функтор | Списарг],
Цель
Здесь получить и вычислить– некоторые определенные пользователем процедуры, предназначенные для вычисления компонент цели. После этого цель порождается предикатом '=..', а затем активизируется при помощи простого указания ее имени Цель.
Некоторые реализации Пролога могут содержать требование, чтобы все цели, появляющиеся в программе, по своей синтаксической форме были либо атомами, либо структурами с атомом в качестве главного функтора. Поэтому переменная, вне
% Отношение
%
% подставить( Подтерм, Терм, Подтерм1, Терм1)
%
% состоит в следующем: если все вхождения Подтерм'а в Терм
% заменить на Подтерм1, то получится Терм1.
%
подставить( Терм, Терм, Терм1, Терм1) :- !.
% Случай 2: нечего подставлять
подставить( _, Терм, _, Терм) :-
atomic( Терм), !.
% Случай 3: Проделать подстановку в аргументах
подставить( Под, Терм, Под1, Терм1) :-
Терм =.. [F | Арги],
% Выделить аргументы
подспис( Под, Арги, Под1, Арги1),
% Выполнить над ними подстановку
Терм1 =.. [F | Арги1].
подспис( Под, [Терм | Термы], Под1, [Терм1 | Термы1]) :-
подставить( Под, Терм, Под1, Терм1),
подспис( Под, Термы, Под1, Термы1).
Рис. 7. 3. Процедура подстановки в терм вместо одного из его
подтермов некоторого другого подтерма.
зависимости от ее текущей конкретизации, может по своей синтаксической форме не подойти в качестве
цели. Эту трудность можно обойти при помощи еще одного встроенного предиката
call
(вызов), чьим аргументом является цель, подлежащая вычислению. В соответствий с этим предыдущий пример должен быть переписан так:
. . .
Цель = [Функтор | Списарг],
саll( Цель)
Иногда нужно извлечь из терма только его главный функтор или один из аргументов. В этом случае можно, конечно, воспользоваться отношением '=..' Но более аккуратным и практичным, а также и более эффективным
способом будет
применение одной из двух новых встроенных процедур:
functor
и
аrg
. Вот их смысл: цель
functor( Терм, F, N)
истинна, если F– главный функтор Tepм'a, а N– арность F. Цель
arg( N, Терм, А)
истинна, если А– N-й аргумент в Терм'е, в предположении, что нумерация аргументов идет слева направо и начинается с 1. Примеры для иллюстрации:
?- functor( t( f( x), X, t), Фун, Арность).