【问题标题】:Prolog: Different behaviour of single and double quotesProlog:单引号和双引号的不同行为
【发布时间】:2015-12-11 01:47:07
【问题描述】:

我对 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(第2行) 当双引号给我false(第4行)?

【问题讨论】:

标签: prolog portability double-quotes prolog-assert


【解决方案1】:

TL;DR1: 阅读this answer 到问题 “What is the difference between ' and " in Prolog?”。

TL;DR2: 目标'id'@987654323@"id" 成功iff Prolog 标志double_quotes 设置为atom .

Prolog flag double_quotes 可以在运行时使用@987654327@ 设置:

  • ?- set_prolog_flag(double_quotes, <i>chars</i>).

    ?-“id”=“id”。
  • ?- set_prolog_flag(double_quotes, <i>codes</i>).

    ?-“id”=“id”。
  • ?- set_prolog_flag(double_quotes, <b>atom</b>).

    ?-“id”=“id”。 是的

有关更多信息,请阅读“Strings as lists”上的SICStus Prolog manual 页面!

【讨论】:

    【解决方案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 个不同的非地面记录。

    底线: 请注意附在 上的“小心轻放”警告标志!

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 2013-12-14
      • 2013-02-16
      • 2013-08-25
      • 2011-01-23
      • 2011-06-02
      • 1970-01-01
      相关资源
      最近更新 更多