定义用户无法查询的规则

如何定义用户无法查询的规则? 我只希望程序本身通过另一个规则调用此规则。 例如: rule1(): - rule2()。 rule2(): - 1< 5。 ?-规则1()。 真正 ?-rule2()。 (我不知道答案是什么,我只是希望这个查询失败!)     
已邀请:
使用Logtalk对象封装谓词。只能调用您声明为public的谓词(从对象外部)。 Prolog模块不会阻止调用任何谓词,因为使用explcit限定会绕过显式导出的谓词列表。 一个简单的例子:
:- object(rules).

    :- public(rule1/1).
    rule1(X) :-
        rule2(X).

    rule2(X) :-
        X < 5.

:- end_object.
编译并加载上面的对象后:
?- rules::rule1(3).
true.

?- rules::rule2(3).
error(existence_error(predicate_declaration,rule2(3)),rules::rule2(3),user)
如果你编辑目标代码并明确地将rule2 / 1声明为私有,那么你会得到错误:
?- rules::rule2(3).
error(permission_error(access,private_predicate,rule2(3)),rules::rule2(3),user)
http://logtalk.org/上的更多信息和大量示例     
这让我想起了Java中的设施。有人可以查询 curent call stack,并使用它来调节调用权限 一个方法。翻译成Prolog,我们在旧的DEC-10 Prolog中找到了 以下谓词: 祖先(L)      将L与当前子句的祖先目标列表统一起来。      该列表以父目标开始,以最新目标结束      祖先来自编译条款中的调用。列表已打印      使用print,每个条目前面都有调用号      括号后跟深度编号(如下所示)      跟踪消息)。如果调用没有数字(这会      如果调试模式没有打开直到进一步执行,则会发生)      然后用“ - ”标记。不适用于已编译的代码。 由于顶级通常是编译的谓词prolog / 0,这可能是 用于编写检查自己的调用堆栈的谓词,然后决定 是否想要投入使用。
rule2 :- ancestors(L), length(L,N), N<2, !, write('Don't call me'), fail.
rule2 :- 1<5.
在现代Prolog中,我们不再经常发现祖先/ 1谓词。 但它可以按以下方式进行模拟。只是抛出错误,然后 如果错误是用堆栈跟踪装饰的,那么您将获得所需的一切:
ancestors(L) :- catch(sys_throw_error(ignore),error(ignore,L),true).
但要注意堆栈消除优化可能会减少堆栈,从而减少堆栈 祖先/ 1返回的列表。 最好的祝福 P.S。:已经解释了堆栈消除优化: [4] Warren,D.H.D。 (1983):抽象Prolog指令集,技术说明309,SRI国际,1983年10月 在这里可以找到Jekejeke Prolog的讨论: http://www.jekejeke.ch/idatab/doclet/prod/en/docs/10_pro08/13_press/03_bench/05_optimizations/03_stack.html     
首先,一些注意事项: 我认为你的意思是“谓词”而不是“规则”。谓词是
name/k
的东西,如
help/0
(和
help/1
是另一个)并且可以有多个子句,其中包括事实和规则,例如
length([], 0).
(事实)和
length([H|T], L) :- ... .
(规则)是一个谓词
length/2
的两个子句。 不要对没有参数的谓词使用空括号 - 至少在SWI-Prolog中,这根本不起作用。只需在所有地方使用
predicate2
而不是
predicate2()
。 如果你试图调用一个未定义的谓词,SWI-Prolog会说
ERROR: toplevel: Undefined procedure: predicate2/0 (DWIM could not correct goal)
而Sicstus-Prolog会说
{EXISTENCE ERROR: predicate2: procedure user:predicate2/0 does not exist}
现在,回答。我想到了两个想法。 (1)这是一个hack,但你可以在每次需要时断言谓词并在之后立即收回它们:
predicate1 :- 
      assert(predicate2), predicate2, retractall(predicate2).
如果你想要一个身体和arguments11ѭ的论据,那就做
assert(predicate2(argument1, argument2) :- (clause1, clause2, clause3))
。 (2)实现此目的的另一种方法是为谓词引入一个额外的参数,您不希望用户调用该参数并将其用于用户无法提供的标识,但您可以通过调用提供该标识。谓语。这可能是一个大的常数,看起来是随机的,甚至是一个句子。这甚至可以让您在提供错误标识的情况下输出自定义错误消息。 例:
 predicate1 :- 
        predicate2("Identification: 2349860293587").

 predicate2(Identification) :- 
        Identification = "Identification: 2349860293587", 
        1 < 5.
 predicate2(Identification) :- Identification = "Identification: 2349860293587",
        write("Error: this procedure cannot be called by the user. Use predicate1/0 instead."), 
        fail.
我没有使用等效的
predicate2("Identification: 2349860293587")
作为
predicate2/0
的第一个子句,因为我不确定该子句的头部可能出现在Prolog消息中的哪个部分,而你不希望这样。我在第二个句子的末尾使用了
fail
,只是为了让Prolog在错误信息之后打印
false
而不是
true
。最后,我不知道如何阻止用户使用
listing(predicate2)
查找源代码,这样如果他/她真的想要,仍然可以简单地查找正确的识别码。如果仅仅是为了防止用户意外受到伤害,它应该足以作为保护。     

要回复问题请先登录注册