2

我对 Prolog 很陌生,我偶然发现了一些我不明白的东西。

这是我的代码:

:- 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当双引号给我(第4行)时,为什么单引号给我(第2false行)?

4

2 回答 2

4

TL;DR 1 阅读Prolog 中“'和'之间的区别是什么?这个问题的答案?”。

TL;DR 2如果Prolog 标志double_quotes设置为 ,目标成功。'id' = "id"atom

Prolog 标志 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 手册页上的“字符串作为列表”!

于 2015-12-24T07:31:39.660 回答
2

假设某些用户在数据库中获得了相同 ID 的多条记录;可能有潜在用途的东西,比如说,如果人们可能有多个名字......无论如何,这个答案不是关于正确建模部分,而是关于的技术方面!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 个不同的地面记录。出:2个不同的非地面记录。

底线: 请注意附加到的“小心处理”警告标志!

于 2015-12-25T09:16:53.517 回答