Prolog
- Русское название:
- Пролог
- Дата создания:
- 1972
- Повлиял на:
- Парадигма:
- Типизация:
- Принятые расширения файлов:
- .pl, .pro
- Диалекты:
- Реализации и версии (свернуть все | развернуть все):
-
- Arity Prolog
- Arity/Prolog32
-
B-Prolog
- B-Prolog 1.0
- B-Prolog 1.2
- B-Prolog 1.5
- B-Prolog 1.6
- B-Prolog 2.0
- B-Prolog 2.1
- B-Prolog 3.0
- B-Prolog 3.1
- B-Prolog 3.2
- B-Prolog 4.0
- B-Prolog 5.0
- B-Prolog 5.0-a
- B-Prolog 5.0-b
- B-Prolog 6.0
- B-Prolog 6.0 beta
- B-Prolog 6.1
- B-Prolog 6.2
- B-Prolog 6.4
- B-Prolog 6.5
- B-Prolog 6.6
- B-Prolog 6.7
- B-Prolog 6.7-1
- B-Prolog 6.7-3
- B-Prolog 6.8
- B-Prolog 6.9
- B-Prolog 7.0
- B-Prolog 7.1beta4
- B-Prolog 7.4-3
- B-Prolog 8.0
- BinProlog
- Brain Aid Prolog
- Ciao Prolog
- CxProlog
- ECLiPSe CLP
- EZY Prolog
- GNU Prolog
- IF/Prolog
- JIProlog
- K-Prolog
- MINERVA
- Open Prolog
- PDC/Turbo Prolog
- Poplog (Prolog)
- Qu-Prolog
- SICStus Prolog
- SWI-Prolog
- Trinc-Prolog
- Visual Prolog
- YAP
Prolog (от “PROgramming in LOGic”) — декларативный язык программирования общего назначения.
Prolog был создан в 1972 с целью сочетать использование логики с представлением знаний. С тех пор у него появился ряд диалектов, расширяющих основу языка различными возможностями.
Стандарт языка дан в ISO/IEC 13211-1 (1995 год).
Prolog — один из старейших и все еще один из наиболее популярных языков логического программирования, хотя он значительно менее популярен, чем основные императивные языки. Он используется в системах обработки естественных языков, исследованиях искусственного интеллекта, экспертных системах, онтологиях и других предметных областях, для которых естественно использование логической парадигмы.
Prolog был создан под влиянием более раннего языка Planner и позаимствовал из него следующие идеи:
- обратный логический вывод (вызов процедур по шаблону, исходя из целей);
- построение структура управляющей логики в виде вычислений с откатами;
- принцип “отрицание как неудача”;
- использование разных имен для разных сущностей и т.д.
Главной парадигмой, реализованной в языке Prolog, является логическое программирование. Как и для большинства старых языков, более поздние реализации, например, Visual Prolog, добавляют в язык более поздние парадигмы, например, объектно-ориентированное или управляемое событиями программирование, иногда даже с элементами императивного стиля.
Prolog использует один тип данных, терм, который бывает нескольких типов:
- атом — имя без особого смысла, используемое для построения составных термов;
- числа и строки такие же, как и в других языках;
- переменная обозначается именем, начинающимся с прописной буквы, и используется как символ-заполнитель для любого другого терма;
- составной терм состоит из атома-функтора, за которым следует несколько аргументов, каждый из которых в свою очередь является атомом.
Программы, написанные на чистом Prolog, описывают отношения между обрабатываемыми сущностями при помощи клауз Хорна. Клауза — это формула вида Голова :- Тело.
, которая читается как “чтобы доказать/решить Голову, следует доказать/решить Тело”. Тело клаузы состоит из нескольких предикатов (целей клаузы), скомбинированных с помощью конъюнкции и дизъюнкции. Клаузы с пустым телом называются фактами и эквивалентны клаузам вида Голова :- true.
(true — не атом, как в других языках, а встроенный предикат).
Другой важной частью Prolog являются предикаты. Унарные предикаты выражают свойства их аргументов, тогда как предикаты с несколькими аргументами выражают отношения между ними. Ряд встроенных предикатов языка выполняют ту же роль, что и функции в других языках, например, ….
Предикаты с несколькими аргументами могут действовать в нескольких направлениях в зависимости от того, какие из аргументов уже связаны, а какие — нет. Например, ….
Наконец, для того, чтобы быть языком общего назначения, Prolog должен предоставлять ряд сервисных функций, например, процедур ввода/вывода. Они реализованы как предикаты без специального логического смысла, которые всегда оцениваются как истинные и выполняют свои сервисные функции как побочный эффект оценивания.
Целью выполнения программы на Prolog является оценивание одного целевого предиката. Имея этот предикат и набор правил и фактов, заданных в программе, Prolog пытается найти привязки (значения) переменных, при которых целевой предикат принимает значение истинности.
…
Структура программы на Прологе отличается от структуры программы, написанной на процедурном языке. Пролог-программа является собранием правил и фактов. Решение задачи достигается интерпретацией этих правил и фактов. При этом пользователю не требуется обеспечивать детальную последовательность инструкций, чтобы указать, каким образом осуществляется управление ходом вычислений на пути к результату. Вместо этого он только определяет возможные решения задачи и обеспечивает программу фактами и правилами, которые позволяют ей отыскать требуемое решение.
Во всех других отношениях Пролог не отличается от традиционных языков программирования. Как и в случае программы написанной на любом другом языке, Пролог-программа предназначена для решения отдельной задачи.
Пролог (Prolog) — язык логического программирования, основанный на логике дизъюнктов Хорна, представляющей собой подмножество логики предикатов первого порядка. Начало истории языка относится к 70-м годам XX века. Будучи декларативным языком программирования, Пролог воспринимает в качестве программы некоторое описание задачи, и сам производит поиск решения, пользуясь механизмом бэктрекинга и унификацией.
Пролог относится к так называемым декларативным языкам, требующим от автора умения составить формальное описание ситуации. Поэтому программа на Прологе не является таковой в традиционном понимании, так как не содержит управляющих конструкций типа if … then, while … do; нет даже оператора присваивания. В Прологе задействованы другие механизмы. Задача описывается в терминах фактов и правил, а поиск решения Пролог берет на себя посредством встроенного механизма логического вывода.
Перечень возможных синтаксических конструкций Пролога невелик, и в этом смысле язык прост для изучения. С другой стороны, декларативный стиль программирования оказывается столь непривычным и новым для опытных программистов, что вызывает шок и в ряде случаев оказывается тормозом.
Пролог реализован практически для всех известных операционных систем и платформ. В число операционных систем входят OS для мэйнфреймов, всё семейство Unix, Windows, OS для мобильных платформ.
Многие современные реализации языка имеют внутреннее расширение за счет ООП-архитектуры. Кроме проприетарных решений, существуют свободные реализации Пролога.
Пролог критикуется в первую очередь за свою недостаточную гибкость, отчего решения на обычных языках программирования (типа C++, Java) в сочетании с базами данных оказываются более технологичными, чем аналогичные решения на Прологе. Негибкость заключается в трудности изучения языка, более высоких требованиях к квалификации программиста на Прологе, трудности отладки программы, неразвитости технологии программирования, плохой контролируемости промежуточных результатов.
Основные вехи развития языка Prolog
Prolog стал воплощением идеи использования логики в качестве языка программирования, которая зародилась в начале 1970-х годов, и само его название является сокращением от слов “programming in logic” (программирование в терминах логики). Первыми исследователями, которые занялись разработкой этой идеи, были Роберт Ковальски (Robert Kowalski) из Эдинбурга (теоретические основы), Маартен ван Эмден (Maarten van Emden) из Эдинбурга (экспериментальная демонстрационная система) и Ален Колмероэ (Alain Colmerauer) из Марселя (реализация). Популяризации языка Prolog во многом способствовала эффективная реализация этого языка в середине 1970-х годов Дэвидом Д. Г. Уорреном (David D.H. Warren) из Эдинбурга. К числу новейших достижений в этой области относятся средства программирования на основе логики ограничений (Constraint Logic Programming — CLP), которые обычно реализуются в составе системы Prolog. Средства CLP показали себя на практике как исключительно гибкий инструмент для решения задач составления расписаний и планирования материально-технического снабжения. А в 1996 году был опубликован официальный стандарт ISO языка Prolog.
Наиболее заметные тенденции в истории развития языка Prolog
В развитии языка Prolog наблюдаются очень интересные тенденции. Этот язык быстро приобрел популярность в Европе как инструмент практического программирования. В Японии вокруг языка Prolog были сосредоточены все разработки компьютеров пятого поколения. С другой стороны, в США этот язык в целом был принят с небольшим опозданием в связи с некоторыми историческими причинами. Одна из них состояла в том, что Соединенные Штаты вначале познакомились с языком Microplanner, который также был близок к идее логического программирования, но неэффективно реализован. Определенная доля низкой популярности Prolog в этой стране объясняется также реакцией на существовавшую вначале “ортодоксальную школу” логического программирования, представители которой настаивали на использовании чистой логики и требовали, чтобы логический подход не был “запятнан” практическими средствами, не относящимися к логике. В прошлом это привело к широкому распространению неверных взглядов на язык Prolog. Например, некоторые считали, что на этом языке можно программировать только рассуждения с выводом от целей к фактам. Но истина заключается в том, что Prolog — универсальный язык программирования и на нем может быть реализован любой алгоритм. Далекая от реальности позиция “ортодоксальной школы” была преодолена практиками языка Prolog, которые приняли более прагматический подход, воспользовавшись плодотворным объединением нового, декларативного подхода с традиционным, процедурным.
Элементы синтаксиса:
Комментарий до конца строки | % |
---|---|
Регистрозависимость | да |
Регулярное выражение идентификатора переменной | [_A-Z][_a-zA-Z0-9]* |
Регулярное выражение идентификатора функции | [_a-z][_a-zA-Z0-9]* |
Присваивание значения переменной | is |
Объявление переменной | = или :- |
Группировка выражений | ( ... ) |
Тождественное равенство | == |
Тождественное неравенство | \== |
Сравнение | @< @=< @> @>= |
Вызов функции | f(a,b,...) |
Вызов функции без параметров | f |
Последовательность | , |
Если - то - иначе | ( A -> B ; C) |
Цикл с постусловием | repeat, ..., condition |
Примеры:
Hello, World!:
Пример для версий Visual Prolog 7.2Visual Prolog создает проекты автоматически. Для запуска примера следует создать новый проект, выбрав “Console” в качестве UI Strategy, перейти к редактированию файла main.pro
и заменить его содержимое приведенным кодом.
implement main
open core
constants
className = "main".
classVersion = "".
clauses
classInfo(className, classVersion).
clauses
run():-
console::init(),
stdio::write("Hello, World!"),
programControl::sleep(1000),
succeed().
end implement main
goal
mainExe::run(main::run).
Факториал:
Пример для версий Visual Prolog 7.2Для запуска создайте новый проект с UI Strategy “Console” и замените содержимое файлов main.cl
и main.pro
приведенным кодом.
В main.cl
добавлена одна строка factorial : (integer N, integer F) procedure (i,o).
, которая определяет бинарный предикат factorial
с известным первым и неизвестным вторым аргументами. Ключевое слово procedure
описывает поведение предиката, указывая, что его вычисление всегда будет успешным и будет найдено ровно одно решение, так что откаты не понадобятся.
В main.pro
находится собственно определение нового предиката. Для каждого его вызова есть два возможных соответствия — с нулевым или произвольным первым аргументом. Visual Prolog перебирает формулы в порядке их появления в коде, так что если первый аргумент равен нулю, проверка начинается с первой формулы factorial(0,F)
. Первое правило формулы — !, так называемое отсечение, использование которого предотвращает откат ко второй формуле и таким образом обеспечивает наличие ровно одного решения предиката. После этого переменная F, содержащая решение предиката, устанавливается в 1 и выводится на печать. Вторая формула factorial(N,F)
рекурсивно вычисляет F1 как факториал N-1, устанавливает решение предиката равным N*F1 и выводит его на печать. Наконец, stdio::nl
печатает новую строку.
При выполнении основной программы предикат factorial
выполняется ровно один раз, для N=12. С каждым вызовом рекурсии N уменьшается на единицу, пока не становится равным нулю. После этого значения факториалов возвращаются и выводятся на печать в порядке возрастания. Программа обрабатывает только факториалы до 12!, т.к. попытка вычисления 13! вызывает ошибку переполнения целочисленного типа.
% main.cl
class main
open core
predicates
classInfo : core::classInfo.
factorial : (integer N, integer F) procedure (i,o).
predicates
run : core::runnable.
end class main
% main.pro
implement main
open core
constants
className = "main".
classVersion = "".
clauses
classInfo(className, classVersion).
factorial(0,F) :-
!,
F = 1,
stdio::write("0! = 1"),
stdio::nl.
factorial(N,F) :-
factorial(N-1,F1),
F = N*F1,
stdio::write(N, "! = ", F),
stdio::nl.
clauses
run():-
console::init(),
factorial(12,F),
programControl::sleep(1000),
succeed().
end implement main
goal
mainExe::run(main::run).
Числа Фибоначчи:
Пример для версий Visual Prolog 7.2В этом примере определяются два новых предиката — бинарный fibonacci(N,F)
для вычисления N-ого числа Фибоначчи и loop(N)
для его вывода на печать. Единожды вычисленные числа не сохраняются для позднейшего использования, поэтому эта реализация неэффективна.
Следует отметить отличие реализаций предикатов от примера для факториала: формулы, описывающие начальные условия, задаются для произвольного значения переменной, но вычисляются до конца только в том случае, если первое правило (N<3
или N=1
, соответственно) оценивается как истинное. Кроме того, каждый предикат записан как одна формула, использующая конъюнкцию и дизъюнкцию, а не как набор отдельных формул, использующих только конъюнкцию.
% main.cl
class main
open core
predicates
classInfo : core::classInfo.
fibonacci : (integer N, integer F) procedure (i,o).
loop : (integer N) procedure (i).
predicates
run : core::runnable.
end class main
% main.pro
implement main
open core
constants
className = "main".
classVersion = "".
clauses
classInfo(className, classVersion).
fibonacci(N,F) :-
N < 3, !, F = 1;
fibonacci(N-1,F1), fibonacci(N-2,F2), F = F1 + F2.
loop(N) :-
( N = 1, !, fibonacci(1,F);
loop(N-1), fibonacci(N,F) ),
stdio::write(F, ", ").
clauses
run():-
console::init(),
loop(16),
stdio::write("..."),
programControl::sleep(1000),
succeed().
end implement main
goal
mainExe::run(main::run).
Hello, World!:
Пример для версий B-Prolog 7.4-3, ECLiPSe CLP 6.0 #188, Poplog 15.5 (Prolog), gprolog 1.3.0, swipl 5.6.xЭтот пример не требует загрузки фактов или правил. Запрос выполняется в интерактивном режиме, и его результат выглядит следующим образом:
Hello, World!
yes
Первая строка является собственно выводом предиката write
, вторая — результат оценивания запроса.
Следует отметить, что замена одинарных кавычек на двойные выводит строку как массив ASCII-кодов отдельных символов:
| ?- write("Hello, World!").
[72,101,108,108,111,44,32,87,111,114,108,100,33]
yes
write('Hello, World!'), nl.
Числа Фибоначчи:
Пример для версий Poplog 15.5 (Prolog)Простая рекурсивная реализация слишком неэффективна с точки зрения памяти, чтобы успешно выполняться в Poplog, поэтому этот пример демонстрирует более сложную технику — рекурсию с запоминанием. Дополнительный предикат memo(Goal)
определяется так, что в первый раз, когда оценивается Goal
, результат оценки добавляется в базу фактов, и при следующем запросе не переоценивается, а используется как известный факт.
После этого предикат fib(N,F)
определяется рекурсивно, но каждый вызов fib
“обернут” в предикат memo
, поэтому для каждого значения N fib(N,F)
оценивается только один раз. При таком подходе печать вычисленных чисел может производиться сразу после их вычисления, без дополнительного цикла.
% fibonacci.pl
:- dynamic(stored/1).
memo(Goal) :-
stored(Goal) -> true;
Goal, assertz(stored(Goal)).
fib(1,1) :- !, write('1, ').
fib(2,1) :- !, write('1, ').
fib(N,F) :-
N1 is N-1, memo(fib(N1,F1)),
N2 is N-2, memo(fib(N2,F2)),
F is F1 + F2,
write(F), write(', ').
% interactive
[-fibonacci].
fib(16,X), write('...'), nl.
Факториал:
Пример для версий Poplog 15.5 (Prolog)Этот пример состоит из двух частей — первую часть кода следует сохранить в файле fact.pl
, расположенном в рабочем каталоге Poplog, а вторую — ввести вручную в интерактивном режиме.
[-fact].
загружает базу фактов и правил из этого файла в текущую сессию Poplog (и выводит сообщение fact reconsulted
, чтобы обозначить успешность загрузки). Запрос fact(16,X).
пытается найти значение X, при котором этот предикат будет оценен как истинный. Вывод, требующийся в примере, будет побочным эффектом оценивания запроса, а основным результатом будет X = 20922789888000 ?
. Это означает, что если вы недовольны такой привязкой переменных, вы можете отказаться от нее (введя ; ), и будет продолжен поиск лучшей привязки.
% fact.pl
fact(X, F) :-
( X=0, F=1;
Y is X-1, fact(Y, Z), F is X*Z),
write(X), write('! = '), write(F), nl.
% interactive
[-fact].
fact(16,X).
Квадратное уравнение:
Пример для версий Visual Prolog 7.2Для запуска создайте новый проект с UI Strategy “Console” и замените содержимое файлов main.cl
и main.pro
приведенным кодом.
В main.cl
добавлена одна строка q : () procedure().
. Ключевое слово procedure
описывает поведение предиката, указывая, что его вычисление всегда будет успешным и будет найдено ровно одно решение, так что откаты не понадобятся.
В main.pro
находится собственно определение нового предиката. Предикат q
не принимает аргументов, поскольку читает необходимые данные из stdio
. Условное оценивание (конструкцияif-then-else
) работает точно так же, как в других языках. Единственным отличием является знак отсечения !
перед then
. Это означает, что как только условие if
выполняется, откат уже не потребуется.
Хитрость этого примера в том, что невозможно сразу вычислить дискриминант, как в других языках. Тип данных по умолчанию для переменной D
в присвоении D = B*B-4*A*C
-uReal
, который может хранить только неотрицательные числа.
% main.cl
class main
open core
predicates
classInfo : core::classInfo.
q : () procedure().
predicates
run : core::runnable.
end class main
% main.pro
implement main
open core
constants
className = "main".
classVersion = "".
clauses
classInfo(className, classVersion).
q() :-
stdio::write("A = "),
A = stdio::read(),
if (A = 0), ! then
stdio::write("Not a quadratic equation."), stdio::nl
else
stdio::write("B = "),
B = stdio::read(),
stdio::write("C = "),
C = stdio::read(),
if (B*B = 4*A*C), ! then
stdio::writef("x = %f", -B/2.0/A)
elseif (B*B > 4*A*C), ! then
D = B*B-4*A*C,
stdio::writef("x1 = %f\n", (-B+math::sqrt(D))/2.0/A),
stdio::writef("x2 = %f", (-B-math::sqrt(D))/2.0/A)
else
D = -B*B+4*A*C,
stdio::writef("x1 = (%f, %f)\n", -B/2.0/A, math::sqrt(D)/2.0/A),
stdio::writef("x2 = (%f, %f)", -B/2.0/A, -math::sqrt(D)/2.0/A)
end if
end if.
clauses
run():-
console::init(),
q(),
succeed().
end implement main
goal
mainExe::run(main::run).
Факториал:
Пример для версий B-Prolog 7.4-3, gprolog 1.3.0, swipl 5.6.xКак в GNU Prolog, так и в B-Prolog 12! не помещается в целочисленный тип данных, поэтому все значения после 11! неправильны. В SWI-Prolog переполнения не возникает.
| ?- [fact].
Результат для GNU Prolog:
compiling /home/nickolas/Desktop/progopedia/prolog/fact.pl for byte code…
/home/nickolas/Desktop/progopedia/prolog/fact.pl compiled, 3 lines read — 1372 bytes written, 5 ms
Результат для B-Prolog:
consulting::fact.pl
`| ?- fact(16,X).
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = -57869312
13! = -215430144
14! = 205203456
15! = -143173632
16! = -143294464
X = -143294464 ?`
% fact.pl
fact(X, F) :-
( X=0, F=1;
Y is X-1, fact(Y, Z), F is X*Z),
write(X), write('! = '), write(F), nl.
% interactive
[fact].
fact(16,X).
Числа Фибоначчи:
Пример для версий B-Prolog 7.4-3, gprolog 1.3.0, swipl 5.6.xПример почти идентичен примеру для Poplog Prolog, за исключением синтаксиса подключения файла.
% fibonacci.pl
:- dynamic(stored/1).
memo(Goal) :-
stored(Goal) -> true;
Goal, assertz(stored(Goal)).
fib(1,1) :- !, write('1, ').
fib(2,1) :- !, write('1, ').
fib(N,F) :-
N1 is N-1, memo(fib(N1,F1)),
N2 is N-2, memo(fib(N2,F2)),
F is F1 + F2,
write(F), write(', ').
% interactive
[fibonacci].
fib(16,X), write('...'), nl.
Квадратное уравнение:
Пример для версий gprolog 1.3.0read_integer
— не стандартный предикат, а расширение GNU Prolog, поэтому этот пример не будет работать в других реализациях.
q :- write('A = '),
read_integer(A),
( A = 0, write('Not a quadratic equation');
write('B = '),
read_integer(B),
write('C = '),
read_integer(C),
D is B*B-4*A*C,
( D = 0, write('x = '), X is -B/2/A, write(X);
D > 0, write('x1 = '), X1 is (-B+sqrt(D))/2/A, write(X1), nl, write('x2 = '), X2 is (-B-sqrt(D))/2/A, write(X2);
R is -B/2/A, I is abs(sqrt(-D)/2/A),
write('x1 = ('), write(R), write(', '), write(I), write(')'), nl,
write('x1 = ('), write(R), write(', -'), write(I), write(')')
)
).
Квадратное уравнение:
Пример для версий B-Prolog 7.4-3, gprolog 1.3.0, swipl 5.6.xЭтот пример соответствует стандарту ISO Prolog и использует встроенный предикат read/1
. Следует отметить, что при вводе термов этим способом после каждого терма следует ставить точку.
q :- write('A = '),
read(A),
( A = 0, write('Not a quadratic equation');
write('B = '),
read(B),
write('C = '),
read(C),
D is B*B-4*A*C,
( D = 0, write('x = '), X is -B/2/A, write(X);
D > 0, write('x1 = '), X1 is (-B+sqrt(D))/2/A, write(X1), nl, write('x2 = '), X2 is (-B-sqrt(D))/2/A, write(X2);
R is -B/2/A, I is abs(sqrt(-D)/2/A),
write('x1 = ('), write(R), write(', '), write(I), write(')'), nl,
write('x1 = ('), write(R), write(', -'), write(I), write(')')
)
).
Факториал:
Пример для версий ECLiPSe CLP 6.0 #188Используется рекурсивное определение факториала.
Для организации цикла в предикате main
используется специфичная для ECLiPSe итеративная управляющая структура (мета-предикат) for
.
factorial(0, 1) :-
!.
factorial(N, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F is N * F1.
main :-
( for(N, 0, 16) do
factorial(N, F),
write(N), write('! = '), write(F), nl ).
Числа Фибоначчи:
Пример для версий ECLiPSe CLP 6.0 #188Числа Фибоначчи вычисляются рекурсивно.
Для организации цикла в предикате main
используется специфичная для ECLiPSe итеративная управляющая структура (мета-предикат) for
.
fibonacci(1, 1) :- !.
fibonacci(2, 1) :- !.
fibonacci(N, F) :-
N > 2,
N1 is N - 1, N2 is N - 2,
fibonacci(N1, F1), fibonacci(N2, F2),
F is F1 + F2.
main :-
( for(N, 1, 16) do
fibonacci(N, F),
write(F), write(', ') ),
writeln('...').
Числа Фибоначчи:
Пример для версий ECLiPSe CLP 6.0 #188Числа Фибоначчи вычисляются рекурсивно, при этом используется мемоизация, реализованная при помощи ECLiPSe-специфичного механизма store
.
Для организации цикла в предикате main
используется специфичная для ECLiPSe итеративная управляющая структура (мета-предикат) for
.
:- local store(fibonacci).
fibonacci(1, 1) :- !.
fibonacci(2, 1) :- !.
fibonacci(N, F) :-
N > 2,
(
% используем сохраненный результат
store_get(fibonacci, N, F), !
;
N1 is N - 1, N2 is N - 2,
fibonacci(N1, F1), fibonacci(N2, F2),
F is F1 + F2,
store_set(fibonacci, N, F) % сохраняем полученный результат
).
main :-
( for(N, 1, 16) do
fibonacci(N, F),
write(F), write(', ') ),
writeln('...').
Комментарии
]]>blog comments powered by Disqus
]]>