Difference between revisions of "VIP7 Construct examples"

From wiki.visual-prolog.com

m (Added foreach reference)
m (link)
 
(14 intermediate revisions by 2 users not shown)
Line 1: Line 1:
This page contains a collection of basic examples for (mainly) the newer constructs found in VIP7.
This page contains a collection of basic examples for (mainly) the newer constructs found in VIP7.
<br><br>
 
=== Fact variables ===
=== Fact variables ===


Fact variables are the only mutable types in VIP.
Fact variables are the only mutable types in VIP.


'''Examples - "reminder- ordinary facts"'''
First, a reminder for ordinary facts:


<vip>facts
<vip>facts
     ndb_int:(integer).  % a nondeterministic fact (0 to any number of values)
     ndb_int : (integer).  % a nondeterministic fact (0 to any number of values)
     db_int:(integer,string) determ. % a deterministic fact (0 to 1 value)</vip>
     db_int : (integer,string) determ. % a deterministic fact (0 to 1 value)</vip>


These types of fact are asserted and retracted.
These types of fact are asserted and retracted.


'''Examples - "fact variables"'''
'''Examples''' (fact variables)
 
<vip>facts
<vip>facts
     zz_int:integer:=0.
     zz_int:integer := 0.
     zz_fred:integer:=erroneous.
     zz_fred:integer := erroneous.


domains
domains
     dom=dom(string,chaindb:ref).
     dom = dom(string,chaindb::ref).


facts
facts
     zz_dom:dom:=erroneous.
     zz_dom : dom := erroneous.


clauses
clauses
     pred():-
     pred() :-
         zz_int:=7,
         zz_int := 7,
         stdio::write("\n zz_int = ",zz_int), %will write "zz_int=7"
         stdio::write("\n zz_int = ", zz_int), %will write "zz_int = 7"
         zz_int:=zz_int+20,
         zz_int := zz_int+20,
         stdio::write("\n zz_int = ",zz_int), %will write "zz_int=27"
         stdio::write("\n zz_int = ", zz_int), %will write "zz_int = 27"
         succeed.</vip>
         succeed.</vip>


A fact variable is great for counting eg.
Fact variables are great for counting e.g.


<vip>predicates
<vip>predicates
     how_many:()->integer Count.
     how_many : () -> integer Count.
clauses
clauses
     how_many()=_:-
     how_many() = zz_int :-
         zz_int:=0,
         zz_int := 0,
         some_nondeterm_fact_or_pred(),
         foreach some_nondeterm_fact_or_pred() do
             zz_int:=zz_int+1,
             zz_int := zz_int+1
            fail.
        end foreach.
    how_many()=zz_int.
 
clauses
clauses
     pred():-
     pred() :-
       stdio::write("\n There are ",how_many()," items").
       stdio::write("\n There are ", how_many(), " items").</vip>
</vip>
<br><br>


=== Lists - findall and list comprehension ===
=== Lists - findall and list comprehension ===


See [http://wiki.visual-prolog.com/index.php?title=Lists_and_Recursion Lists and Recursion]<br>
See [[Lists and Recursion]]
<vp>findall()</vp> has been depricated, so use the list comprehension construct.
<vp>findall()</vp> has been deprecated, so use the list comprehension construct.


'''Examples'''
'''Examples'''
<vip>facts
<vip>facts
     ndb:(integer). %default is nondeterm for a fact
     ndb : (integer). %default is nondeterm for a fact
clauses
clauses
     ndb(1).
     ndb(1).
Line 63: Line 63:
     ....
     ....
     ndb(10).
     ndb(10).
clauses
clauses
     pred_old():-
     pred_old() :-
         findall(X,ndb(X),List).
         findall(X,ndb(X),List).
         %results in List = [1,2,3,4,5,6,7,8,9,10]
         %results in List = [1,2,3,4,5,6,7,8,9,10]
clauses
clauses
     pred_new():-
     pred_new() :-
         List=[X||ndb(X)].
         List = [ X || ndb(X) ].
         %results in List = [1,2,3,4,5,6,7,8,9,10]
         %results in List = [1,2,3,4,5,6,7,8,9,10]
clauses
clauses
     pred_filter():-
     pred_filter() :-
         List=[X||ndb(X), X>6].
         List = [ X || ndb(X), X>6 ].
         %results in List = [7,8,9,10]
         %results in List = [7,8,9,10]


     pred_filter():-
     pred_filter() :-
         List=[X||ndb(X), X mod 2=0].
         List = [ X || ndb(X), X mod 2 = 0 ].
         %results in List = [2,4,6,8,10]
         %results in List = [2,4,6,8,10]


     pred_filter():-
     pred_filter() :-
         List=[X||ndb(X), X mod 2=0, X<7].
         List = [ X || ndb(X), X mod 2 = 0, X<7 ].
         %results in List = [2,4,6]
         %results in List = [2,4,6]


     pred_filter():-
     pred_filter() :-
         zz_int:=0,
         zz_int := 0,
         List=[X||ndb(X), X mod 2=0, X<7, zz_int:=zz_int+1].
         List = [ X || ndb(X), X mod 2 = 0, X<7, zz_int := zz_int+1 ].
         %results in List = [2,4,6] and zz_int=3.
         %results in List = [2,4,6] and zz_int = 3.


     pred_filter():-
     pred_filter() :-
         List=[X||ndb(X), Y=pred2(X), Y>10].  %with pred2(X)=X^2.
         List = [ X || ndb(X), Y = pred2(X), Y>10 ].  %with pred2(X) = X^2.
         %results in List = [4,5,6,7,8,9,10]
         %results in List = [4,5,6,7,8,9,10]
         %reason - X=3 gives Y=9 which is < 10.
         %reason - X = 3 gives Y = 9 which is < 10.


     pred_other():-
     pred_other() :-
         L=[1,2,3,4,5,6,7,8,9,10],
         L = [1,2,3,4,5,6,7,8,9,10],
         LIST=[ X || X = list::getMember_nd(L)].
         LIST = [ X || X = list::getMember_nd(L)].
         %results in List= L
         %results in List = L
 
    pred_other() :-
        Primes =
            [ X || X = std::fromto(1,300),
                L1 = [ Y || Y = std::fromto(2,150) ],
                tt(X,L1) ].
        %results in List = prime numbers, with:


    pred_other():-
        Primes=[X||X=std::fromto(1,300),
L1=[Y||Y=std::fromto(2,150)],
tt(X,L1)].
        %results in List= prime numbers, with:
class predicates
class predicates
         tt:(integer,integer*) determ.
         tt : (integer,integer*) determ.
clauses
clauses
         tt(_X,[]):-!.
         tt(_X,[]) :- !.
         tt(X,[X|_]):-!.
         tt(X,[X|_]) :- !.
         tt(X,[Y|L]):-
         tt(X,[Y|L]) :-
X mod Y<>0,
        X mod Y<>0,
tt(X,L).
        tt(X,L).</vip>


</vip>
<br><br>
=== if-then-else (code) ===
=== if-then-else (code) ===


Line 120: Line 123:


<vip>clauses
<vip>clauses
     pred(X,Y)=Z:-
     pred(X,Y) = Z :-
         if X=0 then
         if X = 0 then
             Z="x is zero"
             Z = "x is zero"
         elseif X>0 then
         elseif X>0 then
             if pred3(Y)=true then
             if pred3(Y) = true then
                 Z="x>0 and pred(Y) is true"
                 Z = "x>0 and pred(Y) is true"
             else
             else
                 Z="x>0 and pred(Y) is false"
                 Z = "x>0 and pred(Y) is false"
             end if  %note, no comma here either
             end if  %note, no comma here either
         else
         else
             Z="x <0"
             Z = "x <0"
         end if.</vip>
         end if.</vip>


<br><br>
=== #if #then #else (directive for conditional compilation) ===
=== #if #then #else (directive for conditional compilation) ===


Line 139: Line 141:


<vip>constants
<vip>constants
     u64_con=1.
     u64_con = 1.
     int_con=2.
     int_con = 2.
     real_con=3.
     real_con = 3.


     compile_big_con=u64_con. %change this and then recompile.
     compile_big_con = u64_con. %change this and then recompile.


#if compile_big_con=u64_con #then
#if compile_big_con = u64_con #then
     predicates
     predicates
         pred:()->unsigned64.
         pred : () -> unsigned64.
     clauses
     clauses
         pred()=U64:-
         pred() = U64 :-
             U64=78766.
             U64 = 78766.


#elseif compile_big_con=int_con #then
#elseif compile_big_con = int_con #then
     predicates
     predicates
         pred:()->integer.
         pred : () -> integer.
     clauses
     clauses
         pred()=Int:-
         pred() = Int :-
             Int=20.
             Int = 20.


#else
#else
     predicates
     predicates
         pred:(real [out]).
         pred : (real [out]).
     clauses
     clauses
         pred(0.766).
         pred(0.766).
Line 167: Line 169:
#endif</vip>
#endif</vip>


'''Note'''<br>
'''Note'''
Code construct uses    <vp>if  - then</vp>,  <vp>elseif  - then</vp>,  <vp>else</vp>,  <vp>end if</vp> <br>
Code construct uses    <vp>if  - then</vp>,  <vp>elseif  - then</vp>,  <vp>else</vp>,  <vp>end if</vp>
compiler directive uses <vp>#if - #then</vp>, <vp>#elseif - #then</vp>, <vp>#else</vp>, <vp>#endif</vp>
compiler directive uses <vp>#if - #then</vp>, <vp>#elseif - #then</vp>, <vp>#else</vp>, <vp>#endif</vp>
<br>(just the "end if" is "different")
(just the "end if" is "different")


<br><br>
=== Trap and try/catch/finally ===
=== Trap and try/catch/finally ===


See [http://wiki.visual-prolog.com/index.php?title=Language_Reference/Terms/Try-catch-finally Try-catch-finally]<br>
See [[Language Reference/Terms/Try-catch-finally|Try-catch-finally]]
Note, in
Note, in [[Language Reference/Built-in entities/Predicates|Built-in entities/Predicates]]
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Built-in_entities/Predicates Built-in entities/Predicates]<br>
suggests using <vp>try-end try</vp> instead of <vp>trap(_,_,_)</vp>
suggests using <vp>try-end try</vp> instead of <vp>trap(_,_,_)</vp>


Line 183: Line 183:


<vip>clauses
<vip>clauses
     pred_all():-
     pred_all() :-
         try
         try
             call_pred_that_might_crash(0)
             call_pred_that_might_crash(0)
Line 193: Line 193:


class predicates
class predicates
     call_pred_that_might_crash:(integer).
     call_pred_that_might_crash : (integer).
     call_own_exception_pred:(pointer ErrorNo).
     call_own_exception_pred : (pointer ErrorNo).
     always_call_this_anyway:().
     always_call_this_anyway : ().
clauses
clauses
     call_pred_that_might_crash(X):-
     call_pred_that_might_crash(X) :-
         Y=9/X.
         Y = 9/X.


     call_own_exception_pred(ErrorNo):-
     call_own_exception_pred(ErrorNo) :-
         vpiCommonDialogs::note("crashed").
         vpiCommonDialogs::note("crashed").


     always_call_this_anyway():-
     always_call_this_anyway() :-
         vpiCommonDialogs::note("finally reached").</vip>
         vpiCommonDialogs::note("finally reached").</vip>


Line 209: Line 209:


<vip>clauses
<vip>clauses
     pred_some():-
     pred_some() :-
         try
         try
             call_pred_that_might_crash(0)
             call_pred_that_might_crash(0)
Line 221: Line 221:


<vip>clauses
<vip>clauses
     pred_some():-
     pred_some() :-
         try
         try
             call_pred_that_might_crash(0)
             call_pred_that_might_crash(0)
Line 231: Line 231:


<vip>clauses
<vip>clauses
     pred_illegal():-
     pred_illegal() :-
         try
         try
             call_pred_that_might_crash(0)
             call_pred_that_might_crash(0)
         end try.</vip>
         end try.</vip>


<br><br>
=== Foreach ===
=== Foreach ===
See  
 
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Terms/Foreach Foreach]
See [[Language Reference/Terms/Foreach|Foreach]]
<br><br>
 
=== 64 bit numbers - history ===
=== 64 bit numbers - history ===
Up to VIP7.1, integer64 etc were defined as:<br>
 
<vip>
Up to VIP7.1, integer64 etc were defined as:
domains
 
<vip>domains
     unsigned64 = unsigned64(unsigned32 Low, unsigned32 High).
     unsigned64 = unsigned64(unsigned32 Low, unsigned32 High).
     integer64 = integer64(unsigned32 Low, integer32 High).
     integer64 = integer64(unsigned32 Low, integer32 High).</vip>
</vip>
 
In VIP7.2 these have been renamed:


In VIP7.2 these have been renamed:<br>
<vip>domains
<vip>
     unsigned64_struct = unsigned64(unsigned Low, unsigned High).
     unsigned64_struct = unsigned64(unsigned Low, unsigned High).
     integer64_struct = integer64(unsigned Low, integer High).
     integer64_struct = integer64(unsigned Low, integer High).</vip>
</vip>


So, for example, in VIP7.1:
So, for example, in VIP7.1:
<vip>
 
<vip>predicates
     getFileProperties : (
     getFileProperties : (
         string FileName,
         string FileName,
Line 264: Line 264:
         core::gmtTimeValue LastAccess,
         core::gmtTimeValue LastAccess,
         core::gmtTimeValue LastChange)
         core::gmtTimeValue LastChange)
         procedure (i,o,o,o,o,o).
         procedure (i,o,o,o,o,o).</vip>
</vip>
 
if you needed use (and write) '''fileSize''' and times, you would have to have done some juggling (such as converting them to real numbers).  
if you needed use (and write) '''fileSize''' and times, you would have to have done some juggling (such as converting them to real numbers).
<br>To generate a 64 bit random number:<br>
 
To generate a 64 bit random number:
 
<vip>predicates %before VIP7.2
<vip>predicates %before VIP7.2
     gen64:()->unsigned64.
     gen64 : () -> unsigned64.
clauses
clauses
     gen64()=U64:-
     gen64() = U64 :-
         N= 2^32,
         N = 2^32,
         Low=math::random(N+0),
         Low = math::random(N+0),
         High=math::random(N+0),
         High = math::random(N+0),
         U64=unsigned64(Low,High).
         U64 = unsigned64(Low,High).</vip>
</vip>
 
and possibly you would have needed (e.g.) '''math::add''':


and possibly you would have needed (e.g.) '''math::add''':<br>
<vip>predicates
    add : (core::unsigned64 Augend, core::unsigned64 Addend) -> core::unsigned64 Sum</vip>


<vip>
It's now totally straightforward in VIP7.2 - just treat 64 bit numbers like any other number. You may also want these conversions - found in '''core::''' - for old code (this snippet is stolen from [http://discuss.visual-prolog.com/viewtopic.php?t=7927 Thomas' post])
    add : (core::unsigned64 Augend, core::unsigned64 Addend) -> core::unsigned64 Sum
</vip>


It's now totally straightforward in VIP7.2 - just treat 64 bit numbers like any other number. You may also want these conversions - found in '''core::''' - for old code (this snippet is stolen from [http://discuss.visual-prolog.com/viewtopic.php?t=7927 Thomas' post]) <br>
<vip>predicates
<vip>
predicates
     toUnsigned64 : (unsigned64_struct) -> unsigned64.
     toUnsigned64 : (unsigned64_struct) -> unsigned64.
     fromUnsigned64 : (unsigned64) -> unsigned64_struct.
     fromUnsigned64 : (unsigned64) -> unsigned64_struct.
     toInteger64 : (integer64_struct) -> integer64.
     toInteger64 : (integer64_struct) -> integer64.
     fromInteger64 : (integer64) -> integer64_struct.
     fromInteger64 : (integer64) -> integer64_struct.</vip>
</vip>
 
<br>
And just for reference:
And just for reference:<br>
* [[Language Reference/Built-in_entities/Domains#integer|integer]] range = -2^31 to +2^31-1 = -2147483648 .. 2147483647
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Built-in_entities/Domains#integer integer] range = -2^31 to +2^31 = -2147483648 .. 2147483647<br>
* [[Language Reference/Built-in_entities/Domains#unsigned|unsigned]]  range = 0 to (2^32)-1 = 4294967295
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Built-in_entities/Domains#unsigned unsigned]  range = 0 to (2^32)-1 = 4294967295<br>
* [[Language Reference/Built-in_entities/Domains#integer64|integer64]] range = -2^63 to 2^63
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Built-in_entities/Domains#integer64 integer64] range = -2^63 to 2^63<br>
* [[Language Reference/Built-in_entities/Domains#unsigned64|unsigned64]] range = 0 to (2^64)-1 = 18446744073709551615 ( = 1.844..E19)
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Built-in_entities/Domains#unsigned64 unsigned64] range= 0 to (2^64)-1 = 18446744073709551615 (=1.844..E19)<br>
<br><br>


=== Polymorphic Domains ===
=== Polymorphic Domains ===
See [http://wiki.visual-prolog.com/index.php?title=Objects_and_Polymorphism Objects and Polymorphism]<br>


First, check out the definitions - '''core::tuple{}'''. And while you're there, just below, see '''core::predicate{}''' and '''core::function{}''', then followed by '''comparator{A}''' and '''list{A}'''.<br>
See {{lang|Objects and Polymorphism|Objects and Polymorphism}}
 
First, check out the definitions - <vp>core::tuple{}</vp>. And while you're there, just below, see <vp>core::predicate{}</vp> and <vp>core::function{}</vp>, then followed by <vp>comparator{A}</vp> and <vp>list{A}</vp>.
 
The domains in class <vp>list::</vp> are polymorphic, but you can define your own polymorphic domains. Here are some examples:


The domains in class '''list::''' are polymorphic, but you can define your own polymorphic domains. Here are some examples:
<vip>domains
<vip>domains
poly_dom{A,B}=poly_def(A,B).
    poly_dom{A,B} = poly_def(A,B).</vip>
</vip>
 
When you use it in your code, A and B can be any other domain.<br>
When you use it in your code, A and B can be any other domain. The domain name is <vp>poly_dom{A,B}</vp>, and you reference it you must use its whole name (not just <vp>poly_dom</vp>) e.g.
The domain name is '''poly_dom{A,B}''', and you reference it you must use its whole name (not just '''poly_dom''') e.g. <br>
 
<vip>
<vip>domains
domains
    joe{A,B} = poly_dom{A,B}*.
joe{A,B}=poly_dom{A,B}*.
/* the next two lines are illegal
/* the next two lines are illegal
poly_dom{A,B}=poly_def(A,B)*.
    poly_dom{A,B} = poly_def(A,B)*.
poly_dom{A,A}=poly_def(A,A).
    poly_dom{A,A} = poly_def(A,A).
*/
*/
fred{A,B}=fred(poly_dom{A,B},integer).
    fred{A,B} = fred(poly_dom{A,B},integer).
 
    maybe_silly_dom{A,B} =
        silly2(A,B);
        silly(A);
        pd(poly_dom{A,B});
        poly_dom(A,B);%IS NOT THE SAME POLY_DOM!! (notice no braces)
        s(string).


maybe_silly_dom{A,B}=silly2(A,B);
    another{A} =
silly(A);
        i(integer);
pd(poly_dom{A,B});
        s(string);
poly_dom(A,B);%IS NOT THE SAME POLY_DOM!! (notice no braces)
        a(A);
s(string).
        self(another({A}).
another{A}=i(integer);
s(string);
a(A);
self(another({A}).


facts
facts
zz_poly_dom:poly_dom{integer,integer}:=erroneous.
    zz_poly_dom:poly_dom{integer,integer} := erroneous.


class predicates
class predicates
p_morphic_test:().  
    p_morphic_test : ().
clauses
clauses
p_morphic_test():-
    p_morphic_test() :-
zz_poly_dom:=poly_def(1,5),
        zz_poly_dom := poly_def(1,5),
call_pd(zz_poly_dom),
        call_pd(zz_poly_dom),
fail.
        fail.
p_morphic_test():-
    p_morphic_test() :-
PD=poly_def(1,["an example","or two"]),
        PD = poly_def(1,["an example","or two"]),
call_pd(PD),
        call_pd(PD),
fail.
        fail.
p_morphic_test():-
    p_morphic_test() :-
Q= [poly_def(X, Y) || X= std::fromTo(1, 4),
        Q = [poly_def(X, Y) || X = std::fromTo(1, 4), Y = std::fromTo(1, 5)],
Y= std::fromTo(1, 5)],
        stdio::write("\n",Q),
stdio::write("\n",Q),
        fail.
fail.
    p_morphic_test().
p_morphic_test().


class predicates
class predicates
call_pd:(poly_dom{A,B}).
    call_pd : (poly_dom{A,B}).
clauses
clauses
call_pd(POLY_DOM):-
    call_pd(POLY_DOM) :-
stdio::write("\n",POLY_DOM),
        stdio::write("\n",POLY_DOM),
fail.
        fail.
call_pd(poly_def(A,B)):-%note this is POLY_DEF
    call_pd(poly_def(A,B)) :- %note this is POLY_DEF
stdio::write("\n",A,B),
        stdio::write("\n",A,B),
fail.
        fail.
call_pd(_).
    call_pd(_).</vip>
 
 
</vip>


<br><br>
=== Properties ===
=== Properties ===


Line 375: Line 371:
<vip>interface fred
<vip>interface fred
     domains
     domains
         complete_dom=is_complete;
         complete_dom = is_complete;
                     not_complete.
                     not_complete.
     properties
     properties
Line 386: Line 382:
implement fred
implement fred
facts
facts
     zz_complete:complete_dom:=erroneous.
     zz_complete:complete_dom := erroneous.


clauses %for the property
clauses %for the property
     prop_complete()=zz_complete. %get
     prop_complete() = zz_complete. %get
     prop_complete(COMPLETE):-zz_complete:=COMPLETE. %set</vip>
     prop_complete(COMPLETE) :- zz_complete := COMPLETE. %set</vip>




Line 398: Line 394:
     open fred
     open fred
clauses
clauses
     pred():-
     pred() :-
         Fred=fred::new(),
         Fred = fred::new(),
         Fred:prop_complete:=is_complete,% to set the value
         Fred:prop_complete := is_complete,% to set the value
         Value=Fred:prop_complete,!. %get</vip>
         Value = Fred:prop_complete, !. %get</vip>
<br><br>
 
=== Comparators and compare ===
=== Comparators and compare ===
First, look at the definition of '''core::comparator''':<br>
 
First, look at the definition of '''core::comparator''':
 
<vip>domains
    comparator{T} = function{T, T, compareResult}.</vip>
 
<vp>compareResult</vp>'s definition can is found here: [[Language Reference/Built-in entities/Domains#compareResult|compareResult]]
 
'''Examples'''
<vip>
class predicates
    p_compare_test : ().
clauses
    p_compare_test() :-
        CompareResult = compare(7,2).
        %will bind CompareResult to '''greater()'''
        %(because 7 > 2)
    p_compare_test() :-
        CompareResult = compare(2,2).
        %will bind CompareResult to '''equal()'''
    p_compare_test() :-
        CompareResult = compare("a","z").
        %will bind CompareResult to '''less()'''</vip>
 
But you may wish to check your own domains to see which is "greater" - and of course you must define this yourself, by defining your own predicate as a '''core::comparator'''
Here is a simple domain in which only the integer parts of the variables are checked to see which is greater:
 
<vip>domains
    s = s(string,integer).
 
class predicates
    compare_it: core::comparator{s}.
clauses
    compare_it(A,B) = CompareResult :- %since this is a core::function(T,T,compareResult)
        A = s(_,I),
        B = s(_,J),
        if I<J then
            CompareResult = less()
        elseif I = J then
            CompareResult = equal()
        else
            CompareResult = greater()
        end if.
 
class predicates
    p_compare_test : ().
clauses
    p_compare_test() :-
        S1 = s("abc",7),
        S2 = s("fred",9),
        CompareResult = compare_it(S1,S2),
        %will give CompareResult = less, since 7<9.</vip>
 
...a bit pointless since the string part of the variables have been ignored, but it is easy to see how to expand <vp>compare_it()</vp> to your own needs.
 
=== list::sortby example using Comparator===
 
list::sortby also uses Compareresult.<br>
 
Say you have the following domain and fact:<br>
<vip>
<vip>
domains
domains
    comparator{T} = function{T, T, compareResult}.
triple=triple(string,gmttimevalue,integer).
facts
zz_triples:triple:=erroneous.
</vip><br>
zz_triples is populated, but it needs to be sorted by date/time. Then:
 
<vip>
clauses
test():-
zz_triples:=list::sortby(cp,zz_triples).
 
predicates
cp:core::comparator{triple}.
clauses
cp(A,B)=CompareResult:-
A=triple(_,ATv,_),
B=triple(_,BTv,_),
GMTA=gmttime::new(Atv),
GMTB=gmttime::new(Btv),
if GMTA:before(GMTB) then
CompareResult=less
else
CompareResult=greater
end if,!.
 
</vip>
</vip>
'''compareResult's''' definition can is found here:
or
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Built-in_entities/Domains#compareResult compareResult]
<br>
'''Examples'''
<vip>
<vip>
class predicates
test():-
p_compare_test:().
zz_triples:=list::sortBy(
clauses
    {(A,B)=CompareResult:-
p_compare_test():-
A=triple(_,ATv,_),
CompareResult=compare(7,2).
B=triple(_,BTv,_),
%will bind CompareResult to '''greater()'''
GMTA=gmttime::new(Atv),
%(because 7 > 2)
GMTB=gmttime::new(Btv),
p_compare_test():-
if GMTA:before(GMTB) then
CompareResult=compare(2,2).
CompareResult=less
%will bind CompareResult to '''equal()'''
else
p_compare_test():-
CompareResult=greater
CompareResult=compare("a","z").
end if},
%will bind CompareResult to '''less()'''
          zz_triples).
</vip>
</vip>
=== list::isMemberBy example using Comparator===


But you may wish to check your own domains to see which is "greater" - and of course you must define this yourself, by defining your own predicate as a '''core::comparator'''<br>
list::isMemberBy also uses Compareresult.<br>
Here is a simple domain in which only the integer parts of the variables are checked to see which is greater:<br>
<vip>
<vip>
domains
domains
s=s(string,integer).
intx=integer.
some_struct=fred(integer*);point(pointer).
class predicates
dom=dom(intx,some_struct).
compare_it: core::comparator{s}.
predicates
clauses
test:().
compare_it(A,B)=CompareResult:-%since this is a core::function(T,T,compareResult)
clauses
A=s(_,I),
test():-
B=s(_,J),
Some_struct=fred([]),
if I<J then
Dom1=dom(1,Some_struct),
CompareResult=less()
Dom2=dom(4,Some_struct),
elseif I=J then
Dom3=dom(9,Some_struct),
CompareResult=equal()
Dom4=dom(7,Some_struct),
Doms=[Dom1,Dom2,Dom3,Dom4],
    if list::isMemberBy(comp,4,Doms) then
    stdio::write("Dom(4,_) found")
else
else
CompareResult=greater()
stdio::write("Dom not found")
end if.
end if.
predicates
class predicates
    comp:comparator{intx,dom}.
p_compare_test:().  
clauses
clauses
    comp(Intx,DOM)=equal:-
p_compare_test():-
    DOM=dom(Intx,_),!.
S1=s("abc",7),
    comp(_,_)=greater.
S2=s("fred",9),
CompareResult=compare_it(S1,S2),
%will give CompareResult=less, since 7<9.
</vip>
</vip>
...a bit pointless since the string part of the variables have been ignored, but it is easy to see how to expand '''compare_it()''' to your own needs.
Also see
<br><br>
[http://wiki.visual-prolog.com/index.php?title=Language_Reference/Terms#Sorting http://wiki.visual-prolog.com/index.php?title=Language_Reference/Terms#Sorting]
 
=== More on core::function and core::predicate ===
=== More on core::function and core::predicate ===
Again, please check out '''core::function''''''core::predicate''' is essentially the same, but does not return a value.<br>
 
Again, please check out <vp>core::function</vp><vp>core::predicate</vp> is essentially the same, but does not return a value.
 
'''Example 1'''
'''Example 1'''
<vip>
 
<vip>class predicates
    two_times:function{integer,integer}.
% or    two_times: core::function{integer,integer}.
clauses
    two_times(A) = 2*A.
class predicates
class predicates
two_times:function{integer,integer}.
    p_function : ().
% or two_times: core::function{integer,integer}.
clauses
clauses
    p_function() :-
two_times(A)=2*A.
        Z = two_times(2),
class predicates
        %binds Z to 4</vip>
p_function:().  
clauses
p_function():-
Z=two_times(2),
%binds Z to 4


</vip>
'''Example 2'''
'''Example 2'''
<vip>
 
domains
<vip>domains
fred_dom{A,B}=predicate{A,B}.
    fred_dom{A,B} = predicate{A,B}.
% or fred_dom{A,B}=core::predicate{A,B}.
% or   fred_dom{A,B} = core::predicate{A,B}.
 
class predicates
class predicates
fred_pred: fred_dom{A,B}.
    fred_pred: fred_dom{A,B}.
clauses
clauses
fred_pred(A,B):-
    fred_pred(A,B) :-
stdio::write("\n",A," ",B).
        stdio::write("\n",A," ",B).
 
class predicates
class predicates
p_pred:().  
    p_pred : ().
clauses
clauses
p_pred():-
    p_pred() :-
fred_pred("one",2).
        fred_pred("one",2).</vip>
</vip>
 
'''Example 3'''
'''Example 3'''
<vip>
 
class predicates
<vip>class predicates
add_func: function{integer,integer}.
    add_func: function{integer,integer}.
clauses
clauses
add_func(B)=B+1.
    add_func(B) = B+1.


class predicates
class predicates
p_function:().  
    p_function : ().
clauses
clauses
p_function():-
    p_function() :-
X=add_func(5),
        X = add_func(5),
%X is bound to 6
        %X is bound to 6</vip>
</vip>
<br><br>


=== Anonymous predicates ===
=== Anonymous predicates ===


''(under development)''
See [[Language Reference/Terms/Anonymous Predicates|Anonymous Predicates]]
See [http://wiki.visual-prolog.com/index.php?title=Language_Reference/Terms/Anonymous_Predicates Anonymous_Predicates]


'''Examples'''
'''Examples'''
Line 518: Line 595:
<vip>clauses
<vip>clauses
     run() :-
     run() :-
         Anon={()=9},
         Anon = {() = 9},
         K=Anon().
         K = Anon().
         %results in K=9
         %results in K = 9
    run() :-
        Anon = { = 88},
        K = Anon().
        %results in K = 88.
    run() :-
        Anon = {(A,B) = A+B},
        K = Anon(4,8),
        %results in K = 12.
     run() :-
     run() :-
        Anon={=88},
         Anon = {
        K=Anon().
             (A,B) = C :-
        %results in K=88.
             R = math::random(7),
    run():-
             C = A+B+R,
        Anon={(A,B)=A+B},
             stdio::wRite("RRRR = ",R)
        K=Anon(4,8),
        %results in K=12.
    run():-
         Anon={
             (A,B)=C:-
             R=math::random(7),
             C=A+B+R,
             stdio::wRite("RRRR=",R)
             },
             },
         K=Anon(4,8).
         K = Anon(4,8).
         %results in K=12 + a random number <7
         %results in K = 12 + a random number <7


     run():-
     run() :-
         Anon={=f_abc(3)},
         Anon = { = f_abc(3)},
         K=Anon(),
         K = Anon(),
         stdio::write("\nI={=f_abc(3)} gives ",K),
         stdio::write("\nI = { = f_abc(3)} gives ",K),
         fail.
         fail.
     run().</vip>
     run().</vip>


=== Threads ===
=== Threads ===
Line 552: Line 628:


<vip>clauses
<vip>clauses
     pred():-
     pred() :-
         _=thread::start(fred).
         _ = thread::start(fred).


predicates
predicates
     fred:().
     fred : ().
clauses
clauses
     fred():-.....</vip>
     fred() :- .....</vip>


fred can have no arguments, so no argument brackets are allowed:
fred can have no arguments, so no argument brackets are allowed:
<vip>
    _=thread::start(fred())</vip>


is illegal. But the thread can access data prepared before it is started.
<vip>    _ = thread::start(fred())</vip>
 
is illegal.  
 
Using [[Language Reference/Terms/Anonymous Predicates|Anonymous Predicates]] is rather simple to pass arguments to thread:


<vip>facts
<vip>clauses
    zz_int:integer:=erroneous.
     pred(X) :-
clauses
         _ = thread::start( { :- fred(X) } ).
     pred():-
        zz_int:=88,
         _=thread::start(fred).


predicates
predicates
     fred:().
     fred : (integer K).
clauses
clauses
     fred():-
     fred(K) :-
        K=zz_int,
         ...</vip>
         ...</vip>
[[Category:Examples]]

Latest revision as of 10:20, 4 July 2017

This page contains a collection of basic examples for (mainly) the newer constructs found in VIP7.

Fact variables

Fact variables are the only mutable types in VIP.

First, a reminder for ordinary facts:

facts
    ndb_int : (integer).  % a nondeterministic fact (0 to any number of values)
    db_int : (integer,string) determ. % a deterministic fact (0 to 1 value)

These types of fact are asserted and retracted.

Examples (fact variables)

facts
    zz_int:integer := 0.
    zz_fred:integer := erroneous.
 
domains
    dom = dom(string,chaindb::ref).
 
facts
    zz_dom : dom := erroneous.
 
clauses
    pred() :-
        zz_int := 7,
        stdio::write("\n zz_int = ", zz_int), %will write "zz_int = 7"
        zz_int := zz_int+20,
        stdio::write("\n zz_int = ", zz_int), %will write "zz_int = 27"
        succeed.

Fact variables are great for counting e.g.

predicates
    how_many : () -> integer Count.
clauses
    how_many() = zz_int :-
        zz_int := 0,
        foreach some_nondeterm_fact_or_pred() do
            zz_int := zz_int+1
        end foreach.
 
clauses
    pred() :-
       stdio::write("\n There are ", how_many(), " items").

Lists - findall and list comprehension

See Lists and Recursion findall() has been deprecated, so use the list comprehension construct.

Examples

facts
    ndb : (integer). %default is nondeterm for a fact
clauses
    ndb(1).
    ndb(2).
    ndb(3).
    ....
    ndb(10).
 
clauses
    pred_old() :-
        findall(X,ndb(X),List).
        %results in List = [1,2,3,4,5,6,7,8,9,10]
 
clauses
    pred_new() :-
        List = [ X || ndb(X) ].
        %results in List = [1,2,3,4,5,6,7,8,9,10]
 
clauses
    pred_filter() :-
        List = [ X || ndb(X), X>6 ].
        %results in List = [7,8,9,10]
 
    pred_filter() :-
        List = [ X || ndb(X), X mod 2 = 0 ].
        %results in List = [2,4,6,8,10]
 
    pred_filter() :-
        List = [ X || ndb(X), X mod 2 = 0, X<7 ].
        %results in List = [2,4,6]
 
    pred_filter() :-
        zz_int := 0,
        List = [ X || ndb(X), X mod 2 = 0, X<7, zz_int := zz_int+1 ].
        %results in List = [2,4,6] and zz_int = 3.
 
    pred_filter() :-
        List = [ X || ndb(X), Y = pred2(X), Y>10 ].   %with pred2(X) = X^2.
        %results in List = [4,5,6,7,8,9,10]
        %reason - X = 3 gives Y = 9 which is < 10.
 
    pred_other() :-
        L = [1,2,3,4,5,6,7,8,9,10],
        LIST = [ X || X = list::getMember_nd(L)].
        %results in List = L
 
    pred_other() :-
        Primes =
            [ X || X = std::fromto(1,300),
                L1 = [ Y || Y = std::fromto(2,150) ],
                tt(X,L1) ].
        %results in List = prime numbers, with:
 
class predicates
        tt : (integer,integer*) determ.
clauses
        tt(_X,[]) :- !.
        tt(X,[X|_]) :- !.
        tt(X,[Y|L]) :-
        X mod Y<>0,
        tt(X,L).

if-then-else (code)

Examples

clauses
    pred(X,Y) = Z :-
        if X = 0 then
            Z = "x is zero"
        elseif X>0 then
            if pred3(Y) = true then
                Z = "x>0 and pred(Y) is true"
            else
                Z = "x>0 and pred(Y) is false"
            end if  %note, no comma here either
        else
            Z = "x <0"
        end if.

#if #then #else (directive for conditional compilation)

Examples

constants
    u64_con = 1.
    int_con = 2.
    real_con = 3.
 
    compile_big_con = u64_con. %change this and then recompile.
 
#if compile_big_con = u64_con #then
    predicates
        pred : () -> unsigned64.
    clauses
        pred() = U64 :-
            U64 = 78766.
 
#elseif compile_big_con = int_con #then
    predicates
        pred : () -> integer.
    clauses
        pred() = Int :-
            Int = 20.
 
#else
    predicates
        pred : (real [out]).
    clauses
        pred(0.766).
 
#endif

Note Code construct uses if  - then, elseif  - then, else, end if compiler directive uses #if - #then, #elseif - #then, #else, #endif (just the "end if" is "different")

Trap and try/catch/finally

See Try-catch-finally Note, in Built-in entities/Predicates suggests using try-end try instead of trap(_,_,_)

Example 1

clauses
    pred_all() :-
        try
            call_pred_that_might_crash(0)
        catch ErrorNo do
            call_own_exception_pred(ErrorNo)
        finally
            always_call_this_anyway()
        end try.
 
class predicates
    call_pred_that_might_crash : (integer).
    call_own_exception_pred : (pointer ErrorNo).
    always_call_this_anyway : ().
clauses
    call_pred_that_might_crash(X) :-
        Y = 9/X.
 
    call_own_exception_pred(ErrorNo) :-
        vpiCommonDialogs::note("crashed").
 
    always_call_this_anyway() :-
        vpiCommonDialogs::note("finally reached").

Example 2

clauses
    pred_some() :-
        try
            call_pred_that_might_crash(0)
        finally
            always_call_this_anyway()
        end try.

% in this case, VIP will automatically pop up its exception dialog

Example 3

clauses
    pred_some() :-
        try
            call_pred_that_might_crash(0)
        catch ErrorNo do
            call_own_exception_pred(ErrorNo)
        end try.

Example 4 - illegal - it must have a catch or finally

clauses
    pred_illegal() :-
        try
            call_pred_that_might_crash(0)
        end try.

Foreach

See Foreach

64 bit numbers - history

Up to VIP7.1, integer64 etc were defined as:

domains
    unsigned64 = unsigned64(unsigned32 Low, unsigned32 High).
    integer64 = integer64(unsigned32 Low, integer32 High).

In VIP7.2 these have been renamed:

domains
    unsigned64_struct = unsigned64(unsigned Low, unsigned High).
    integer64_struct = integer64(unsigned Low, integer High).

So, for example, in VIP7.1:

predicates
     getFileProperties : (
        string FileName,
        fileSystem_api::fileAttributes Attributes,
        fileSystem_api::fileSize Size,
        core::gmtTimeValue Creation,
        core::gmtTimeValue LastAccess,
        core::gmtTimeValue LastChange)
        procedure (i,o,o,o,o,o).

if you needed use (and write) fileSize and times, you would have to have done some juggling (such as converting them to real numbers).

To generate a 64 bit random number:

predicates %before VIP7.2
    gen64 : () -> unsigned64.
clauses
    gen64() = U64 :-
        N = 2^32,
        Low = math::random(N+0),
        High = math::random(N+0),
        U64 = unsigned64(Low,High).

and possibly you would have needed (e.g.) math::add:

predicates
    add : (core::unsigned64 Augend, core::unsigned64 Addend) -> core::unsigned64 Sum

It's now totally straightforward in VIP7.2 - just treat 64 bit numbers like any other number. You may also want these conversions - found in core:: - for old code (this snippet is stolen from Thomas' post)

predicates
    toUnsigned64 : (unsigned64_struct) -> unsigned64.
    fromUnsigned64 : (unsigned64) -> unsigned64_struct.
    toInteger64 : (integer64_struct) -> integer64.
    fromInteger64 : (integer64) -> integer64_struct.

And just for reference:

  • integer range = -2^31 to +2^31-1 = -2147483648 .. 2147483647
  • unsigned range = 0 to (2^32)-1 = 4294967295
  • integer64 range = -2^63 to 2^63
  • unsigned64 range = 0 to (2^64)-1 = 18446744073709551615 ( = 1.844..E19)

Polymorphic Domains

See Objects and Polymorphism

First, check out the definitions - core::tuple{}. And while you're there, just below, see core::predicate{} and core::function{}, then followed by comparator{A} and list{A}.

The domains in class list:: are polymorphic, but you can define your own polymorphic domains. Here are some examples:

domains
    poly_dom{A,B} = poly_def(A,B).

When you use it in your code, A and B can be any other domain. The domain name is poly_dom{A,B}, and you reference it you must use its whole name (not just poly_dom) e.g.

domains
    joe{A,B} = poly_dom{A,B}*.
/* the next two lines are illegal
    poly_dom{A,B} = poly_def(A,B)*.
    poly_dom{A,A} = poly_def(A,A).
*/
    fred{A,B} = fred(poly_dom{A,B},integer).
 
    maybe_silly_dom{A,B} =
        silly2(A,B);
        silly(A);
        pd(poly_dom{A,B});
        poly_dom(A,B);%IS NOT THE SAME POLY_DOM!! (notice no braces)
        s(string).
 
    another{A} =
        i(integer);
        s(string);
        a(A);
        self(another({A}).
 
facts
    zz_poly_dom:poly_dom{integer,integer} := erroneous.
 
class predicates
    p_morphic_test : ().
clauses
    p_morphic_test() :-
        zz_poly_dom := poly_def(1,5),
        call_pd(zz_poly_dom),
        fail.
    p_morphic_test() :-
        PD = poly_def(1,["an example","or two"]),
        call_pd(PD),
        fail.
    p_morphic_test() :-
        Q = [poly_def(X, Y) || X = std::fromTo(1, 4), Y = std::fromTo(1, 5)],
        stdio::write("\n",Q),
        fail.
    p_morphic_test().
 
class predicates
    call_pd : (poly_dom{A,B}).
clauses
    call_pd(POLY_DOM) :-
        stdio::write("\n",POLY_DOM),
        fail.
    call_pd(poly_def(A,B)) :- %note this is POLY_DEF
        stdio::write("\n",A,B),
        fail.
    call_pd(_).

Properties

Properties in a class are used almost identically to fact variables, but properties can be set directly (from another class), without having to declare a public predicate to make the change.

Example

interface fred
    domains
        complete_dom = is_complete;
                     not_complete.
    properties
        prop_complete : complete_dom.
end interface fred

In fred.pro:

implement fred
facts
    zz_complete:complete_dom := erroneous.
 
clauses %for the property
    prop_complete() = zz_complete. %get
    prop_complete(COMPLETE) :- zz_complete := COMPLETE. %set


In some other class that calls class fred:

implement other
    open fred
clauses
    pred() :-
        Fred = fred::new(),
        Fred:prop_complete := is_complete,% to set the value
        Value = Fred:prop_complete, !. %get

Comparators and compare

First, look at the definition of core::comparator:

domains
    comparator{T} = function{T, T, compareResult}.

compareResult's definition can is found here: compareResult

Examples

class predicates
    p_compare_test : ().
clauses
    p_compare_test() :-
        CompareResult = compare(7,2).
        %will bind CompareResult to '''greater()'''
        %(because 7 > 2)
    p_compare_test() :-
        CompareResult = compare(2,2).
        %will bind CompareResult to '''equal()'''
    p_compare_test() :-
        CompareResult = compare("a","z").
        %will bind CompareResult to '''less()'''

But you may wish to check your own domains to see which is "greater" - and of course you must define this yourself, by defining your own predicate as a core::comparator Here is a simple domain in which only the integer parts of the variables are checked to see which is greater:

domains
    s = s(string,integer).
 
class predicates
    compare_it: core::comparator{s}.
clauses
    compare_it(A,B) = CompareResult :- %since this is a core::function(T,T,compareResult)
        A = s(_,I),
        B = s(_,J),
        if I<J then
            CompareResult = less()
        elseif I = J then
            CompareResult = equal()
        else
            CompareResult = greater()
        end if.
 
class predicates
    p_compare_test : ().
clauses
    p_compare_test() :-
        S1 = s("abc",7),
        S2 = s("fred",9),
        CompareResult = compare_it(S1,S2),
        %will give CompareResult = less, since 7<9.

...a bit pointless since the string part of the variables have been ignored, but it is easy to see how to expand compare_it() to your own needs.

list::sortby example using Comparator

list::sortby also uses Compareresult.

Say you have the following domain and fact:

domains
	triple=triple(string,gmttimevalue,integer).
facts
	zz_triples:triple:=erroneous.


zz_triples is populated, but it needs to be sorted by date/time. Then:

clauses
	test():-
		zz_triples:=list::sortby(cp,zz_triples).
 
predicates
	cp:core::comparator{triple}.
clauses
	cp(A,B)=CompareResult:-
		A=triple(_,ATv,_),
		B=triple(_,BTv,_),
		GMTA=gmttime::new(Atv),
		GMTB=gmttime::new(Btv),
		if GMTA:before(GMTB) then
			CompareResult=less
		else
			CompareResult=greater
		end if,!.

or

	test():-
		zz_triples:=list::sortBy(
    			{(A,B)=CompareResult:-
				A=triple(_,ATv,_),
				B=triple(_,BTv,_),
				GMTA=gmttime::new(Atv),
				GMTB=gmttime::new(Btv),
				if GMTA:before(GMTB) then
					CompareResult=less
				else
					CompareResult=greater
				end if},
	           	zz_triples).

list::isMemberBy example using Comparator

list::isMemberBy also uses Compareresult.

domains
	intx=integer.
	some_struct=fred(integer*);point(pointer).
	dom=dom(intx,some_struct).
predicates
	test:().
clauses
	test():-
		Some_struct=fred([]),
		Dom1=dom(1,Some_struct),
		Dom2=dom(4,Some_struct),
		Dom3=dom(9,Some_struct),
		Dom4=dom(7,Some_struct),
		Doms=[Dom1,Dom2,Dom3,Dom4],
    		if list::isMemberBy(comp,4,Doms) then
    			stdio::write("Dom(4,_) found")
		else
			stdio::write("Dom not found")
		end if.
predicates
    comp:comparator{intx,dom}.
clauses
    comp(Intx,DOM)=equal:-
    	DOM=dom(Intx,_),!.
    comp(_,_)=greater.

Also see http://wiki.visual-prolog.com/index.php?title=Language_Reference/Terms#Sorting

More on core::function and core::predicate

Again, please check out core::function. core::predicate is essentially the same, but does not return a value.

Example 1

class predicates
    two_times:function{integer,integer}.
% or    two_times: core::function{integer,integer}.
clauses
    two_times(A) = 2*A.
class predicates
    p_function : ().
clauses
    p_function() :-
        Z = two_times(2),
        %binds Z to 4

Example 2

domains
    fred_dom{A,B} = predicate{A,B}.
% or    fred_dom{A,B} = core::predicate{A,B}.
 
class predicates
    fred_pred: fred_dom{A,B}.
clauses
    fred_pred(A,B) :-
        stdio::write("\n",A," ",B).
 
class predicates
    p_pred : ().
clauses
    p_pred() :-
        fred_pred("one",2).

Example 3

class predicates
    add_func: function{integer,integer}.
clauses
    add_func(B) = B+1.
 
class predicates
    p_function : ().
clauses
    p_function() :-
        X = add_func(5),
        %X is bound to 6

Anonymous predicates

See Anonymous Predicates

Examples

clauses
    run() :-
        Anon = {() = 9},
        K = Anon().
        %results in K = 9
    run() :-
        Anon = { = 88},
        K = Anon().
        %results in K = 88.
    run() :-
        Anon = {(A,B) = A+B},
        K = Anon(4,8),
        %results in K = 12.
    run() :-
        Anon = {
            (A,B) = C :-
            R = math::random(7),
            C = A+B+R,
            stdio::wRite("RRRR = ",R)
            },
        K = Anon(4,8).
        %results in K = 12 + a random number <7
 
    run() :-
        Anon = { = f_abc(3)},
        K = Anon(),
        stdio::write("\nI = { = f_abc(3)} gives ",K),
        fail.
    run().

Threads

To start a thread:

clauses
    pred() :-
        _ = thread::start(fred).
 
predicates
    fred : ().
clauses
    fred() :- .....

fred can have no arguments, so no argument brackets are allowed:

    _ = thread::start(fred())

is illegal.

Using Anonymous Predicates is rather simple to pass arguments to thread:

clauses
    pred(X) :-
        _ = thread::start( { :- fred(X) } ).
 
predicates
    fred : (integer K).
clauses
    fred(K) :-
        ...