Guy*_*der 5 directive prolog dcg iso-prolog
我通过SWI-Prolog学到了很难的方法,Prolog指令的位置set_prolog_flag在源代码文件中很重要.
我发现有关使用指令加载源代码文件的唯一文档是在加载Prolog源文件中
指令是编译器的指令.指令用于设置(谓词)属性(请参阅第4.15节),设置标志(请参阅set_prolog_flag/2)和加载文件(本节).指令是形式的术语: - <term>.
是否有SWI-Prolog的文档,其中包含源代码的加载,如果指令适用于整个文件或取决于源代码文件中的位置,则会注意到这些文档的加载?
或者是从源代码文件加载的所有行只是简单地将语句播放到顶层并且位置始终很重要?
在Prolog中使用明确的句子语法(DCG)时,已知DCG要求输入是字符代码列表,例如
?- string_codes("abc123",Cs).
Cs = [97, 98, 99, 49, 50, 51].
Run Code Online (Sandbox Code Playgroud)
并在源代码文件中使用以下DCG规则并加载到顶级
digit(0) --> "0".
Run Code Online (Sandbox Code Playgroud)
DCG可以使用
?- string_codes("0",Cs),phrase(digit(D),Cs,R).
Cs = [48],
D = 0,
R = []
Run Code Online (Sandbox Code Playgroud)
现在,为了更容易使用DCG而不必使用string_codesProlog指令
:- set_prolog_flag(double_quotes, chars).
Run Code Online (Sandbox Code Playgroud)
可以在源代码文件中使用,并在源代码文件中使用以下DCG规则并加载到顶级
digit(0) --> "0".
Run Code Online (Sandbox Code Playgroud)
DCG可以使用
?- phrase(digit(D),"0",R).
D = 0,
R = [].
Run Code Online (Sandbox Code Playgroud)
事实证明,if 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 = [].
Run Code Online (Sandbox Code Playgroud)
VS
digit(0) --> "0".
:- set_prolog_flag(double_quotes, chars).
?- phrase(digit(D),"0",R).
false.
Run Code Online (Sandbox Code Playgroud)
虽然我知道Prolog的很多编程都可以在顶层完成,但我倾向于依赖源代码文件并咨询/ 1.
在编写大量代码时,我开始使用模块.通过模块,我发现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.
Run Code Online (Sandbox Code Playgroud)
并且默认的顶级模块是 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.
Run Code Online (Sandbox Code Playgroud)
这使我误解了Prolog指令set_prlog_flag适用于整个模块,无论它写在何处.
在编写大量示例代码时,将所有小示例保存在一个文件中并与每个小示例相关联更容易set_prolog_flag.对于标识符示例,它需要两个小的示例DCG规则,一个用于数字,一个用于字母.数字规则高于字母规则和工作,但字母规则有set_prolog_flag指令,因为我当时正在处理它们.请记住,我认为该指令此时适用于整个文件.然后在测试identDCG规则时,字母正在工作,但数字的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'].
Run Code Online (Sandbox Code Playgroud)
所以使用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.
Run Code Online (Sandbox Code Playgroud)
?- 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.
Run Code Online (Sandbox Code Playgroud)
问题很明显
digit(0, [48|B], A) :- !,
A=B.
letter(a, [a|B], A) :- !,
A=B.
Run Code Online (Sandbox Code Playgroud)
该数字已转换为使用字符代码,48并且字母已转换为使用字符a.就在那时我问自己set_prolog_flag源头的位置是否重要.
为了测试这个,我创建了一个小的源代码文件
digit_before(0) --> "0".
:- set_prolog_flag(double_quotes, chars).
digit_after(0) --> "0".
Run Code Online (Sandbox Code Playgroud)
在顶级
?- 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
Run Code Online (Sandbox Code Playgroud)
这证实了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值是首选,因为它使调试时更容易读取值等.
在SWI-Prolog 中,指令和子句按顺序处理。Prolog 标志很复杂。总体规则是它们是线程范围的,其中子线程使用写时复制语义共享其创建者的标志,这实际上意味着除了性能和内存使用之外,所有标志都将被复制。但是,某些标志的范围仅限于它们出现的源文件。这意味着 load_files/2 在加载之前保存标志的状态并在加载之后恢复它。其他一些标志是模块范围的,这意味着标志 API 只是更改模块属性的代理。此类标志不是特定于线程的,因为模块是全局的。另请注意,某些标志会影响读取(例如,double_quotes),而其他标志会影响编译器(optimise),并且大多数会影响运行时行为。
理想情况下, current_prolog_flag/2的文档应该记录这些方面。不确定该文档是否准确。因为double_quotes它说为每个模块维护。
| 归档时间: |
|
| 查看次数: |
306 次 |
| 最近记录: |