Prolog DCG set_prolog_flag double_quotes source code for location; documentation?

I found out that with SWI-Prolog, the set_prolog_flag directive set_prolog_flag has a value in the source code file.

The only documentation I found about downloading source code files with directives was in Downloading Prolog Source Files

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

Is there documentation for SWI-Prolog that covers downloading source code that notes whether the directive applies to the entire file or depends on the location in the source code file?

Or are all the lines loaded from the source code file just a game of operators at the top level, and location always matters?

Supplement / TL; DR

Default

When using Grammars (DCG) in Prolog, as you know, DCG requires the input list to be a list of character codes, for example.

 ?- string_codes("abc123",Cs). Cs = [97, 98, 99, 49, 50, 51]. 

and with the following DCG rule in the source file and uploaded to the top level

 digit(0) --> "0". 

DCG can be used with

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

set_prolog_flag

Now, to simplify the use of DCG instead of using the string_codes directive

 :- set_prolog_flag(double_quotes, chars). 

can be used in the source code file and with the following DCG rule in the source code file and loaded into the upper level

 digit(0) --> "0". 

DCG can be used with

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

There was nothing important about it.

It turns out that if set_prolog_flag appears before the DCG rule and then skips string_codes , but if set_prolog_flag appears after , the DCG rule then skips string_codes not working.

 :- set_prolog_flag(double_quotes, chars). digit(0) --> "0". ?- phrase(digit(D),"0",R). D = 0, R = []. 

vs

 digit(0) --> "0". :- set_prolog_flag(double_quotes, chars). ?- phrase(digit(D),"0",R). false. 

The motives that brought me to me

Although I know that a lot of programming with Prolog can only be done at the top level, I tend to rely on source and consult / 1 files.
When writing a lot of code, I started using modules . With modules, I found that Prolog flags are independent for each module.

 ?- 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. 

and that the default top-level module is 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. 

which put me to the false belief that the Prolog directive set_prlog_flag applicable to the whole module no matter where it was written.

What broke the mold

When writing a large number of code examples, it was easier to save all the small examples in one file and the set_prolog_flag associated with each small example was. As an example of an identifier, he needed two small examples of DCG rules, one for numbers and one for letters. The rules of numbers were higher than the rules of writing and worked, but the rules of letters had the set_prolog_flag directive, because I was working on them at that time. Remember that I think the directive applies to the entire file at the moment. Then, when testing ident , the DCG rules for letters worked, but the DCG rules for numbers did not work.

 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']. 

Root cause

So using 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. 

the problem was obvious

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

this digit was converted to use character codes 48 , and the letter was converted to use characters a . This is when I asked myself if the value of set_prolog_flag in the source.

Confirmation of the root cause

To test this, I created a small source code

 digit_before(0) --> "0". :- set_prolog_flag(double_quotes, chars). digit_after(0) --> "0". 

and at the top level

 ?- 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 

which confirmed that the set_prolog_flag directive set_prolog_flag does not apply to the entire file. Note that digit_before is converted to 48 , and digit_after is converted to '0' .

Notes

Note. The set_prolog_flag(F,V) directive can also be used at the top level and does not require the foregoing :- .

Note. An example is used :- set_prolog_flag(double_quotes, chars). but :- set_prolog_flag(double_quotes, codes). . Using a chars value is preferred because it makes reading values ​​easier when debugging, etc.

+5
source share
2 answers

I can say that you can make sure that the set_prolog_flag(double_quotes, chars) directive set_prolog_flag(double_quotes, chars) has the desired behavior (applicable to the whole file).

This can be done using the initialization/2. directive initialization/2. with the after_load option or using initialization/1.

 digit_before(0) --> "0". :- initialization( set_prolog_flag(double_quotes, chars), after_load ). digit_after(0) --> "0". 

SWI-Prolog initialization / 2 directive

Initialization Directive SWI-Prolog / 1

Regarding the question of how to offer ideas to the SWI-Prolog community, I hope that the (initial) solution is to have a second answer.

Useful links:

Research papers by Ulrich Neumerkel and Fred Mesnar

Main page of Marcus Triski

Contains a large variety of materials on the Prolog programming language.

+2
source

In SWI-Prolog, directives and sentences are processed in order. Prolog flags are complex. The general rule is that they are associated with threads, where child threads share flags from their creator using copy-on-write semantics, which in fact means the same thing as copying all flags except for performance and memory usage . But then some flags are tied to the source file in which they appear. This means that load_files / 2 saves the flag state before loading and restores it later. Some other flags are modules, which means that the flags API is just a proxy for modifying a module attribute. These flags are thread independent, since the modules are global. Also note that some flags affect reading (e.g. double_quotes ), while others affect the compiler ( optimise ), and most affect runtime behavior.

Ideally, documentation with current_prolog_flag / 2 should document these aspects. Not sure if this documentation is accurate. For double_quotes it says it is supported for each module.

+2
source

Source: https://habr.com/ru/post/1270352/


All Articles