gpt4 book ai didi

Prolog DCG set_prolog_flag double_quotes 源代码指令位置很重要;文件?

转载 作者:行者123 更新时间:2023-12-04 12:28:15 25 4
gpt4 key购买 nike

我通过 SWI-Prolog 学到了 Prolog 指令 ​​set_prolog_flag 的位置。在源代码文件中很重要。

我发现关于使用指令加载源代码文件的唯一有值(value)的文档是 Loading Prolog source files

A directive is an instruction to the compiler. Directives are used to set (predicate) properties (see section 4.15), set flags (see set_prolog_flag/2) and load files (this section). Directives are terms of the form :- <term>.



是否有 SWI-Prolog 的文档涵盖了源代码的加载,说明指令是否适用于整个文件或取决于源代码文件中的位置?

还是从源代码文件加载的所有行只是将语句简单地播放到顶层并且位置总是很重要?

补充/TL;DR

默认

在 Prolog 中使用定从句语法 (DCG) 时,已知 DCG 要求输入是字符代码列表,例如
?- string_codes("abc123",Cs).
Cs = [97, 98, 99, 49, 50, 51].

并在源代码文件中使用以下 DCG 规则并加载到顶层
digit(0) --> "0".

DCG 可以与
?- string_codes("0",Cs),phrase(digit(D),Cs,R).
Cs = [48],
D = 0,
R = []

set_prolog_flag

现在让使用 DCG 变得更容易,而不必使用 string_codes Prolog 指令
:- set_prolog_flag(double_quotes, chars).

可以在源代码文件中使用,并在源代码文件中使用以下 DCG 规则并加载到顶层
digit(0) --> "0".

DCG 可以与
?- phrase(digit(D),"0",R).
D = 0,
R = [].

遗漏了一些重要的东西

事实证明,如果 set_prolog_flag出现 之前 DCG 规则然后跳过 string_codes有效,但如果 set_prolog_flag出现 之后 DCG 规则然后跳过 string_codes失败。
:- set_prolog_flag(double_quotes, chars).
digit(0) --> "0".

?- phrase(digit(D),"0",R).
D = 0,
R = [].

对比
digit(0) --> "0".
:- set_prolog_flag(double_quotes, chars).

?- phrase(digit(D),"0",R).
false.

导致我犯规的理由

虽然我知道许多使用 Prolog 的编程都可以在顶层完成,但我倾向于依赖源代码文件和 consult/1 .
在编写大量代码时,我开始使用 modules .对于模块,我发现 Prolog 标志对于每个模块都是独立的。
?- current_prolog_flag(double_quotes,V).
V = string.

?- current_prolog_flag(symbolic:double_quotes,V).
V = string.

?- set_prolog_flag(symbolic:double_quotes,chars).
true.

?- current_prolog_flag(double_quotes,V).
V = string.

?- current_prolog_flag(symbolic:double_quotes,V).
V = chars.

并且默认的顶级模块是 user
?- current_prolog_flag(double_quotes,V).
V = string.

?- current_prolog_flag(user:double_quotes,V).
V = string.

?- set_prolog_flag(double_quotes,chars).
true.

?- current_prolog_flag(double_quotes,V).
V = chars.

?- current_prolog_flag(user:double_quotes,V).
V = chars.

?- set_prolog_flag(user:double_quotes,codes).
true.

?- current_prolog_flag(double_quotes,V).
V = codes.

?- current_prolog_flag(user:double_quotes,V).
V = codes.

这让我误以为 Prolog 指令 ​​ set_prlog_flag应用于整个模块,无论它是在哪里编写的。

什么打破了模具

在编写大量示例代码时,将所有小示例保存在一个文件中更容易,并且与每个小示例相关联的是 set_prolog_flag .对于标识符示例,它需要两个小示例 DCG 规则,一个用于数字,一个用于字母。数字规则高于字母规则并且有效,但字母规则有 set_prolog_flag指令,因为我当时正在研究它们。请记住,我认为该指令此时适用于整个文件。然后在测试 ident字母的 DCG 规则有效,但数字的 DCG 规则失败。
digit(0) --> "0", !.
digit(1) --> "1", !.
digit(2) --> "2", !.

:- set_prolog_flag(double_quotes, chars).

ident(Id) --> letter(C), identr(Cs), { name(Id, [C|Cs]) }.

identr([C|Cs]) --> letter(C), !, identr(Cs).
identr([C|Cs]) --> digit(C), !, identr(Cs).
identr([]) --> [].

letter(a) --> "a", !.
letter(b) --> "b", !.
letter(c) --> "c", !.

?- phrase(ident(Id),"ab12",R).
Id = ab,
R = ['1', '2'].

根本原因

所以使用 listing/1
?- listing(digit).
digit(0, [48|B], A) :- !,
A=B.
digit(1, [49|B], A) :- !,
A=B.
digit(2, [50|B], A) :- !,
A=B.
?- listing(ident).
ident(C, A, F) :-
letter(D, A, B),
identr(E, B, G),
name(C, [D|E]),
F=G.

?- listing(identr).
identr([A|D], B, F) :-
letter(A, B, C), !,
E=C,
identr(D, E, F).
identr([A|D], B, F) :-
digit(A, B, C), !,
E=C,
identr(D, E, F).
identr([], A, A).

?- listing(letter).
letter(a, [a|B], A) :- !,
A=B.
letter(b, [b|B], A) :- !,
A=B.
letter(c, [c|B], A) :- !,
A=B.

问题很明显
digit(0, [48|B], A) :- !,
A=B.

letter(a, [a|B], A) :- !,
A=B.

该数字已转换为使用字符代码 48和字母被转换为使用字符 a .那时我问自己 set_prolog_flag 的位置是否在源很重要。

确认根本原因

为了测试这一点,我创建了一个小源代码文件
digit_before(0) --> "0".

:- set_prolog_flag(double_quotes, chars).

digit_after(0) --> "0".

并在顶层
?- current_prolog_flag(double_quotes,V).
V = string.

?- current_prolog_flag(symbolic:double_quotes,V).
V = string.

?- consult("C:/Users/Eric/Documents/Projects/Calculus Project/test.pl").
true.

?- current_prolog_flag(double_quotes,V).
V = chars.

?- current_prolog_flag(symbolic:double_quotes,V).
V = string.

?- listing(digit_before).
digit_before(0, [48|A], A).

true.

?- listing(digit_after).
digit_after(0, ['0'|A], A).

true

这证实了 Prolog 指令 ​​ set_prolog_flag不适用于整个文件。注意 digit_before 被转换为 48并且 digit_after 被转换为 '0' .

笔记

注意:指令 set_prolog_flag(F,V)也可以在顶层使用,不需要前面的 :- .

注意:示例使用 :- set_prolog_flag(double_quotes, chars).但是 :- set_prolog_flag(double_quotes, codes).也有效。使用 chars value 是首选,因为它使值在调试等时更易于阅读。

最佳答案

在 SWI-Prolog 中,指令和子句按顺序处理。 Prolog 标志很复杂。总体规则是它们是线程范围的,其中子线程使用写时复制语义从其创建者那里共享标志,这实际上意味着除了性能和内存使用之外,所有标志都将被复制。但是,一些标志的范围仅限于它们出现的源文件。这意味着 load_files/2 在加载之前保存标志的状态并在之后恢复它。其他一些标志是模块范围的,这意味着标志 API 只是更改模块属性的代理。这些标志不是特定于线程的,因为模块是全局的。另请注意,某些标志会影响读取(例如 double_quotes ),而其他标志会影响编译器( optimise )并且大多数会影响运行时行为。

理想情况下,带有 current_prolog_flag/2 的文档应该记录这些方面。不确定此文档是否准确。对于 double_quotes它说为每个模块维护。

关于Prolog DCG set_prolog_flag double_quotes 源代码指令位置很重要;文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45390050/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com