Difference between revisions of "VIP7 Construct examples"

From wiki.visual-prolog.com

Line 258: Line 258:
</vip>
</vip>


In VIP72 these have been renamed:<br>
In VIP7.2 these have been renamed:<br>
<vip>
<vip>
     unsigned64_struct = unsigned64(unsigned Low, unsigned High).
     unsigned64_struct = unsigned64(unsigned Low, unsigned High).
Line 276: Line 276:
</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><br>To generate a 64 bit random number:<br>
<br>To generate a 64 bit random number:<br>
<br><vip>predicates %before VIP7.2
<vip>predicates %before VIP7.2
     gen64:()->unsigned64.
     gen64:()->unsigned64.
clauses
clauses
Line 286: Line 286:
         U64=unsigned64(Low,High).
         U64=unsigned64(Low,High).
</vip>
</vip>
and possibly you would have needed (e.g.) '''math::add''':<br>
and possibly you would have needed (e.g.) '''math::add''':<br>
<br><vip>
 
<vip>
     add : (core::unsigned64 Augend, core::unsigned64 Addend) -> core::unsigned64 Sum
     add : (core::unsigned64 Augend, core::unsigned64 Addend) -> core::unsigned64 Sum
</vip>
</vip>
Line 299: Line 301:
     fromInteger64 : (integer64) -> integer64_struct.
     fromInteger64 : (integer64) -> integer64_struct.
</vip>
</vip>
<br>
And just for reference:<br>
::integer range -2147483648 .. 2147483647
::unsigned range 0 .. 4294967295
::unsigned64 range 0 .. 18446744073709551615
<br><br>
<br><br>



Revision as of 18:40, 23 March 2009

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.

Examples - "reminder- 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.

A fact variable is great for counting eg.

predicates
    pred:()=integer Count.
clauses
    pred()=_:-
        zz_int:=0,
        some_nondeterm_fact_or_pred(),
            zz_int:=zz_int+1,
            fail.
    pred()=zz_int.



Lists - findall and list comprehension

See Lists and Recursion
findall() has been depricated, 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):-
        if X>0 then
            stdio::write("\n X>0")  %the last line in each block has no comma
        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
            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.




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:

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

So, for example, in VIP7.1:

     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:

    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 -2147483648 .. 2147483647
unsigned range 0 .. 4294967295
unsigned64 range 0 .. 18446744073709551615



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.



Anonymous predicates

(under development) 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. But the thread can access data prepared before it is started.

facts
    zz_int:integer:=erroneous.
clauses
    pred():-
        zz_int:=88,
        _=thread::start(fred).
 
predicates
    fred:().
clauses
    fred():-
        K=zz_int,
        ...