Discussions related to Visual Prolog
Li
Posts: 12
Joined: 21 Dec 2014 4:15

two queries about swi-prolog and visual-prolog

Unread post by Li »

Dear friends:

In swi-prolog I can do such thing "sentence --> nounphrase, verbphrase."

The "-->" which is called DCG(Definite Clasue Grammer).

and in swi-prolog I can take ";" as "if else" to use.

Whether can visual prolog do things like above? :D :D :D
I am a rookee coming here to learn from friends.
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

Let us start with the simple one: ";" is a backtracking "or" both in swi-Prolog and in Visual Prolog. I.e. means the same.

Visual Prolog does not (directly) support Definite Clause Grammars (DCG).

DCG is however a quite simple syntactic sugaring.

Code: Select all

sentence --> nounphrase, verbphrase
Is simply short for

Code: Select all

clauses     sentence(S1, S0) :-         nounphrase(S1, S2),         verbphrase(S2, S3),         S0 = S3. % S0 is normally used directly instead of S3
I.e. each nonterminal is extended with an input and an output argument, the overall input becomes input in the first nonterminal, each output goes as input to the next, and the final output becomes the overall output.

Semantic actions (enclosed in { .. }) are treated as regular predicate calls. So

Code: Select all

sentence --> nounphrase, {action}, verbphrase
means

Code: Select all

clauses     sentence(S1, S0) :-         nounphrase(S1, S2),         action(),         verbphrase(S2, S0).
Terminals (enclosed in [ .. ]) means match a list head. So

Code: Select all

sentence --> ["The"], nounphrase, {action}, verbphrase
means:

Code: Select all

clauses     sentence(S1, S0) :-         ["The"|S2] = S1,         nounphrase(S2, S3),         action(),         verbphrase(S3, S0).
Maybe (my memory is not completely "fresh" on this matter) the list match is actually performed in an auxiliary predicate:

Code: Select all

clauses     sentence(S1, S0) :-         match(["The"], S1, S2),         nounphrase(S2, S3),         action(),         verbphrase(S3, S0).
The grammar clauses can use additional argumentswhich are simply maintained in the translation. So

Code: Select all

sentence(sentence(N,V)) --> ["The"], nounphrase(N), {action}, verbphrase(V)
Means:

Code: Select all

clauses     sentence(sentence(N,V), S1, S0) :-         match(["The"], S1, S2),         nounphrase(N, S2, S3),         action(),         verbphrase(V, S3, S0).
Regards Thomas Linder Puls
PDC
Li
Posts: 12
Joined: 21 Dec 2014 4:15

Unread post by Li »

Wow,Thomas,you are a genius.Thank you :D :D

The "DCG" is perfectly solved beyond my expectation.

And I have tested the ";" again.There is a problem here.When I define such a predicate:

class predicates
fact:(integer N, integer Res) procedure (i,o).
clauses
fact(N, F) :-
(N<=1,F=1);
(N>1,fact(N-1, F1),F=F1*N).

I thought the "fact" should be "procedure",but it results in "nondeterm"

ERROR: 'fact/2 (i,o)', which is declared as 'procedure', is actually 'nondeterm'

Where is it wrong? :D :D :D
I am a rookee coming here to learn from friends.
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

N <= 1 and N >1 are:
  • complete: all integers are handled
  • non-overlapping: no integer match both cases
But the compiler does not make this kind of reasoning, it just sees two determ cases combined with a backtracking "or", and that gives a nondeterm result.

To convince the "dumb" compiler that you have a procedure, you will either have to use cut and "external" reasoning:

Code: Select all

clauses     fact(N, F) :-         (N <= 1, !, F = 1);         (fact(N-1, F1), F = F1 * N).


If the first case match the cut (!) will remove the backtrack point to the second case, so the predicate can no longer return with an active backtrack point, the second case omits the test (we will only get to the second case if the first case fails i.e. if not(N <= 1) which is the same as N > 1) so the compiler sees something that always succeeds. And therefore the compiler now sees a procedure.

Alternatively, and to keep a declarative cut-less reading of the program you can use the if-then-else construction (which you will not find in swi-Prolog):

Code: Select all

clauses     fact(N, F) :-         if N <= 1 then             F = 1)         else             fact(N-1, F1),             F = F1 * N        end if.
As a final update I will suggest creating a function instead (also not in swi-Prolog):

Code: Select all

class predicates     fact : (integer N) -> integer Fac. clauses     fact(N) = F :-         if N <= 1 then             F = 1         else             F = N * fact(N-1)         end if.
Or skipping the variable F using an if-then-else expression instead:

Code: Select all

class predicates     fact : (integer N) -> integer Fac. clauses     fact(N) = if N <= 1 then 1 else N * fact(N-1) end if.
Have you been through the Fundamental Visual Prolog Tutorials?
Regards Thomas Linder Puls
PDC
Post Reply