Difference between revisions of "VIP7 Construct examples"

From wiki.visual-prolog.com

m (Polymorphic Domains)
m (link)
 
(36 intermediate revisions by 2 users not shown)
Line 5: Line 5:
 
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
     pred:()=integer Count.
+
     how_many : () -> integer Count.
 
clauses
 
clauses
     pred()=_:-
+
     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.
     pred()=zz_int.</vip>
+
 
 +
clauses
 +
     pred() :-
 +
      stdio::write("\n There are ", how_many(), " items").</vip>
  
 
=== 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 58: 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() :-
 +
        L = [1,2,3,4,5,6,7,8,9,10],
 +
        LIST = [ X || X = list::getMember_nd(L)].
 +
        %results in List = L
  
     pred_other():-
+
     pred_other() :-
         L=[1,2,3,4,5,6,7,8,9,10],
+
         Primes =
        LIST=[ X || X = list::getMember_nd(L)].
+
            [ X || X = std::fromto(1,300),
         %results in List= L
+
                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>
 
  
 
=== if-then-else (code) ===
 
=== if-then-else (code) ===
Line 115: Line 123:
  
 
<vip>clauses
 
<vip>clauses
    pred(X):-
+
     pred(X,Y) = Z :-
        if X>0 then
+
         if X = 0 then
            stdio::write("\n X>0")  %the last line in each block has no comma
+
             Z = "x is zero"
        else
 
            stdio::write("\n X<=0")
 
        end if.
 
 
 
    pred(X):-
 
        if X>0 then
 
            stdio::write("\n X>0")
 
        elseif X = 0 then
 
            stdio::write("\n X=0")
 
        else
 
            stdio::write("\n X<0")
 
        end if.
 
 
 
clauses
 
     pred(X,Y)=Z:-
 
         if X=0 then
 
             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>
 
  
 
=== #if #then #else (directive for conditional compilation) ===
 
=== #if #then #else (directive for conditional compilation) ===
Line 151: 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 179: 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")
  
 
=== 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 194: 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 204: 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 220: 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 232: 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 242: 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>
  
 +
=== Foreach ===
 +
 +
See [[Language Reference/Terms/Foreach|Foreach]]
 +
 +
=== 64 bit numbers - history ===
 +
 +
Up to VIP7.1, integer64 etc were defined as:
 +
 +
<vip>domains
 +
    unsigned64 = unsigned64(unsigned32 Low, unsigned32 High).
 +
    integer64 = integer64(unsigned32 Low, integer32 High).</vip>
 +
 +
In VIP7.2 these have been renamed:
 +
 +
<vip>domains
 +
    unsigned64_struct = unsigned64(unsigned Low, unsigned High).
 +
    integer64_struct = integer64(unsigned Low, integer High).</vip>
 +
 +
So, for example, in VIP7.1:
 +
 +
<vip>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).</vip>
  
=== 64 bit 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).
 +
 
 +
To generate a 64 bit random number:
 +
 
 +
<vip>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).</vip>
 +
 
 +
and possibly you would have needed (e.g.) '''math::add''':
 +
 
 +
<vip>predicates
 +
    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])
 +
 
 +
<vip>predicates
 +
    toUnsigned64 : (unsigned64_struct) -> unsigned64.
 +
    fromUnsigned64 : (unsigned64) -> unsigned64_struct.
 +
    toInteger64 : (integer64_struct) -> integer64.
 +
    fromInteger64 : (integer64) -> integer64_struct.</vip>
 +
 
 +
And just for reference:
 +
* [[Language Reference/Built-in_entities/Domains#integer|integer]] range = -2^31 to +2^31-1 = -2147483648 .. 2147483647
 +
* [[Language Reference/Built-in_entities/Domains#unsigned|unsigned]]  range = 0 to (2^32)-1 = 4294967295
 +
* [[Language Reference/Built-in_entities/Domains#integer64|integer64]] range = -2^63 to 2^63
 +
* [[Language Reference/Built-in_entities/Domains#unsigned64|unsigned64]] range = 0 to (2^64)-1 = 18446744073709551615 ( = 1.844..E19)
  
 
=== Polymorphic Domains ===
 
=== Polymorphic Domains ===
See [http://wiki.visual-prolog.com/index.php?title=Objects_and_Polymorphism Objects and Polymorphism]<br>
 
  
 +
See {{lang|Objects and Polymorphism|Objects and Polymorphism}}
  
First, check out the definitions - '''core::tuple'''. And while you're there, just below, see '''core::predicate''' and '''core::function'''<br>
+
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).
 +
 
 +
    another{A} =
 +
        i(integer);
 +
        s(string);
 +
        a(A);
 +
        self(another({A}).
  
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)
 
integer(B);% er...no complaint from the compiler, so go on - be strange
 
string.
 
 
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>
 
  
 
=== Properties ===
 
=== Properties ===
Line 320: Line 371:
 
<vip>interface fred
 
<vip>interface fred
 
     domains
 
     domains
         complete_dom=is_complete;
+
         complete_dom = is_complete;
                not_complete.
+
                    not_complete.
 
     properties
 
     properties
 
         prop_complete : complete_dom.
 
         prop_complete : complete_dom.
 
end interface fred</vip>
 
end interface fred</vip>
  
In fred.pro:
+
In '''fred.pro''':
  
<vip>facts
+
<vip>
     zz_complete:complete_dom:=erroneous.
+
implement fred
 +
facts
 +
     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 341: 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>
 +
 
 +
=== Comparators and compare ===
 +
 
 +
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>
 +
domains
 +
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>
 +
or
 +
<vip>
 +
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).
 +
</vip>
 +
=== list::isMemberBy example using Comparator===
 +
 
 +
list::isMemberBy also uses Compareresult.<br>
 +
<vip>
 +
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.
 +
</vip>
 +
Also see
 +
[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 ===
  
=== Comparators and compare ===
+
Again, please check out <vp>core::function</vp>.  <vp>core::predicate</vp> is essentially the same, but does not return a value.
 +
 
 +
'''Example 1'''
 +
 
 +
<vip>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</vip>
 +
 
 +
'''Example 2'''
 +
 
 +
<vip>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).</vip>
 +
 
 +
'''Example 3'''
 +
 
 +
<vip>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</vip>
  
 
=== 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 358: 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 392: 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 11: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) :-
        ...