Пролог: Различное поведение одинарных и двойных кавычек

Я довольно новичок в Прологе и наткнулся на то, чего не понимаю.

Это мой код:

:- dynamic user/3.
user('id', 'Name', 20).

changeAge(Id, NewAge) :-
   user(Id, Name, _),
   retract(user(Id,_,_)),
   assert(user(Id,Name,NewAge)).

Чтобы обновить информацию о пользователе в базе данных,changeAge/2 выполняет эти три шага:

  1. Поиск правильной записи, используя user/3,
  2. Удалить одну подходящую запись из базы данных, используя retract/1,
  3. Вставьте новую обновленную запись в базу данных, используя assert/1,

Это мой консольный вывод:

1 ?- user('id', _, Age).
Age = 20.

2 ?- changeAge('id', 25).
true.

3 ?- user('id', _, Age).
Age = 25.

4 ?- changeAge("id", 30).
false.

5 ?- user('id', _, Age).
Age = 25.

Почему одинарные кавычки дают мне true (строка 2), когда двойные кавычки дают мне false (строка 4)?

2 ответа

Решение

TL; DR1: Прочтите этот ответ на вопрос "В чем разница между" и "Пролог"?".

TL; DR2: цель 'id' = "id" успешно, если флаг Prolog double_quotes установлен в atom,

Флаг Пролог double_quotes может быть установлен во время выполнения с помощью set_prolog_flag/2:

  • ?- set_prolog_flag(double_quotes, chars).

    ?- 'id' = "id".ложь
  • ?- set_prolog_flag(double_quotes, codes).

    ?- 'id' = "id".ложь
  • ?- set_prolog_flag(double_quotes, atom).

    ?- 'id' = "id".правда

Для получения дополнительной информации прочитайте страницу руководства SICStus Prolog " Строки как списки"!

Допустим, некоторые пользователи получили несколько записей для одного и того же идентификатора в базе данных; что-то, что может иметь потенциальное применение, скажем, если у людей может быть более одного имени... в любом случае, этот ответ не о правильной части моделирования, а о технических аспектах /questions/tagged/prolog-assert! YMMV.

:- dynamic(user/3).

init_db :-
   retractall(user(_,_,_)),
   maplist(assert, [user(i,n,1),user(i,n,2),user(i,m,1),user(i,m,2),
                    user(j,n,1),user(j,n,2),user(j,m,1),user(j,m,2)]).

changeAge(Id, NewAge) :-
   user(Id, Name, _),
   retract(user(Id,_,_)),
   assert(user(Id,Name,NewAge)).

Давайте инициализируем базу данных и "изменим возраст":-)

?- init_db, (changeAge(i,6) ; changeAge(j,7)), false.
false.

?- findall(user(Id,Name,Age), user(Id,Name,Age), DB).
DB = [user(i,m,6),user(i,m,6),user(i,m,6),user(i,m,6),
      user(j,m,7),user(j,m,7),user(j,m,7),user(j,m,7)].

Плохой! в: 8 различных записей. out: 2 разных записи, каждая из которых имеет кратность 4.

Давайте восстановим исходные факты, а затем используем changeAge/2 немного по-другому:

?- init_db, changeAge(_,_), false.
false.

?- findall(user(Id,Name,Age), user(Id,Name,Age), DB).
DB = [user(i,m,_),user(i,m,_),user(i,m,_),user(i,m,_),
      user(j,m,_),user(j,m,_),user(j,m,_),user(j,m,_)].

Еще хуже! в: 8 различных наземных записей. out: 2 разных незаземленных записи.

Итог: будьте внимательны с предупреждающим знаком "обращайтесь с осторожностью", прикрепленным к прологу-заявить!

Другие вопросы по тегам