Prolog:单引号和双引号的不同行为
Prolog: Different behaviour of single and double quotes
我是 Prolog 的新手,我偶然发现了一些我不明白的东西。
这是我的代码:
:- dynamic user/3.
user('id', 'Name', 20).
changeAge(Id, NewAge) :-
user(Id, Name, _),
retract(user(Id,_,_)),
assert(user(Id,Name,NewAge)).
要更新数据库中的用户信息,
changeAge/2
执行这三个步骤:
- 查找正确的记录,使用
user/3
。
- 从数据库中删除一条匹配记录,使用
retract/1
。
- 使用
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 行)?
TL;DR1:
阅读 this answer 问题
“What is the difference between ' and " in Prolog?”。
TL;DR2: 目标'id'<a href="https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/mpg_002dref_002dunify.html" rel="nofollow noreferrer"> = </a>"id"
succeeds iff the Prolog flag double_quotes 设置为 atom
.
Prolog flag double_quotes
can be set at runtime using <a href="https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/mpg_002dref_002dset_005fprolog_005fflag.html" rel="nofollow noreferrer">set_prolog_flag/2</a>
:
?- set_prolog_flag(double_quotes, <i>chars</i>).
?- 'id' = "id".
false.
?- set_prolog_flag(double_quotes, <i>codes</i>).
?- 'id' = "id".
false.
?- set_prolog_flag(double_quotes, <b>atom</b>).
?- 'id' = "id".
true.
有关详细信息,请阅读 SICStus Prolog manual page on "Strings as lists"!
假设一些用户在数据库中获得了同一个 ID 的多条记录;可能有潜在用途的东西,比如说,如果人们可能有多个名字……不管怎样,这个答案不是关于正确建模部分,而是关于 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)).
让我们初始化数据库然后"change some ages" :-)
?- 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 个不同的记录。输出: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 个不同的非地面记录。
底线:
请注意附加到 prolog-assert!
的 "handle with care" 警告标志
我是 Prolog 的新手,我偶然发现了一些我不明白的东西。
这是我的代码:
:- dynamic user/3.
user('id', 'Name', 20).
changeAge(Id, NewAge) :-
user(Id, Name, _),
retract(user(Id,_,_)),
assert(user(Id,Name,NewAge)).
要更新数据库中的用户信息,
changeAge/2
执行这三个步骤:
- 查找正确的记录,使用
user/3
。 - 从数据库中删除一条匹配记录,使用
retract/1
。 - 使用
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 行)?
TL;DR1: 阅读 this answer 问题 “What is the difference between ' and " in Prolog?”。
TL;DR2: 目标'id'<a href="https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/mpg_002dref_002dunify.html" rel="nofollow noreferrer"> = </a>"id"
succeeds iff the Prolog flag double_quotes 设置为 atom
.
Prolog flag double_quotes
can be set at runtime using <a href="https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/mpg_002dref_002dset_005fprolog_005fflag.html" rel="nofollow noreferrer">set_prolog_flag/2</a>
:
?- set_prolog_flag(double_quotes, <i>chars</i>).
?- 'id' = "id". false.
?- set_prolog_flag(double_quotes, <i>codes</i>).
?- 'id' = "id". false.
?- set_prolog_flag(double_quotes, <b>atom</b>).
?- 'id' = "id". true.
有关详细信息,请阅读 SICStus Prolog manual page on "Strings as lists"!
假设一些用户在数据库中获得了同一个 ID 的多条记录;可能有潜在用途的东西,比如说,如果人们可能有多个名字……不管怎样,这个答案不是关于正确建模部分,而是关于 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)).
让我们初始化数据库然后"change some ages" :-)
?- 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 个不同的记录。输出: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 个不同的非地面记录。
底线: 请注意附加到 prolog-assert!
的 "handle with care" 警告标志