New Features in Visual Prolog 7.0 Alpha

Prolog Development Center offers you an oppotunity to try Visual Prolog 7.0 Alpha that is supplied together with the Commercial and Personal Edition of Visual Prolog 6.3.

Visual Prolog version 7.0 will extends the language with several new features.

Polymorphism

Visual Prolog 7.0 introduces (parametric) polymorphism.  You can declare parameterized domains.  For example:

domains
    binTree{Elem} =
        node(binTree{Elem} Left, Elem Node, binTree{Elem} Right);
        leaf().

Such a polymorphic domain replaces a complete range of (non-polymorphic) domains:

domains
    bintree_integer =
        node(bintree_integer Left, integer Node, bintree_integer Right);
        leaf().

domains
    bintree_string =
        node(bintree_string Left, string Node, bintree_string Right);
        leaf().

...

Moreover, polymorphic predicates can manipulate the polymorphic data structures.  This predicate will insert a node in an ordered binary tree:

predicates
    insert : (Elem NewNode, binTree{Elem} Tree) -> binTree{Elem} NewTree.
clauses
    insert(NewNode, leaf()) = node(leaf(), NewNode, leaf()).
    insert(NewNode, node(Left, Node, Right)) = NewTree :-
        NewNode <= Node,
        !,
        NewTree = node(insert(NewNode, Left), Node, Right).
    insert(NewNode, node(Left, Node, Right)) = NewTree :-
        NewTree = node(Left, Node, insert(NewNode, Right)).

This single predicate can insert elements in any kind of binTree's:

clauses
    ppp() :-
        StrTree1 = insert("AAA", leaf()),
        StrTree2 = intert("BBB", StrTree1),
        IntTree1 = insert(17, leaf()),
        IntTree2 = insert(23, IntTree1),
        ...

Polymorphism guarantees type safety, meaning that you cannot insert an integer into a string tree:

clauses
    ppp() :-
        StrTree1 = insert("AAA", leaf()),
        SomeTree2 = insert(23, StrTree1),  % type error
        ...

Such errors are detected at compile time.

In object-oriented programming languages, it is quite common to create data structures like the binary tree using object as an element type:

domains
    bintree_object =
        node(bintree_object Left, object Node, bintree_object Right);
        leaf().

Since any object can be converted to object, you can insert any object in such a binary tree.  However, this has certain drawbacks (all stemming from the same cause):

  • If you have a tree of "windows", you can insert a "person" object in the tree (because they are all objects)
  • When you extract an element from the tree it will have the object type and, therefore, you will have to convert it back to its original type.

These drawbacks do not exist for polymorphic domains:  all the elements in the tree are guarantied to have the same type, and, when you retrieve an element from the tree, it will have exactly that type.  (This type can, of course, be object if you like).

Lists

List domains are polymorphic domains.  Therefore, it is possible to "reuse" list predicates for any kinds of lists:

predicates
    isMember : (Elem Elem, Elem* List) determ.
clauses
    isMember(Elem, [Head|Tail]) :-
        Elem = Head
        or isMember(Elem, Tail).

This predicate can be used on integer lists:

isMember(17, [23, 45, 32, 17, 58])

It can also be used on string lists:

isMember("aaa", ["asd", "asd", "asd"])

But you cannot use it like this:

isMember("aaa", [23, 45, 32, 17, 58]) % type error

And lists like this does not exist:

L = [23, "aaa", 32, 17, 58] % type error

"if-then-else" construction

if-then-else is introduced as a language construction:

clauses
    p(X) = Y :-
        if X = 1 then
            Z = 3
        else
            Z = 7
        end if,
        Y = 2*Z.

If then else can also be used without the else part:

clauses
    p(X) = Y :-
        if trace = true() then
            writef("Started p(%)\n", X)
        end if,
        ...

Deeply Nested "or"

In Visual Prolog 7.0, it will be possible to nest "or" deeply in clauses.

clauses
    p(X) = Y :-
        (X = 1, !, Z = 3 or Z = 7), Y = 2*Z.

Here we have used the keyword "or", but you can also use semi-colon ";".

We recommend a careful usage of "or"; it is mainly intended for usage in if-then-else constructions:

clauses
    p(X) :-
        if X = 1 or X > 17 then
            ...
        end if.

Foreach

New language construction for each:

…,
foreach p_nd(X) do
   write(X), nl()
end foreach,
…

The foreach construction is intended as a replacement for fail loops:

…,
p_nd(X)
   write(X), nl()
fail.

However, the "foreach" construction succeeds, when the iteration is completed.  So computation will continue right after the "foreach" construction (rather than in the next clause).

…,
foreach p_nd(X) do
   write(X), nl()
end foreach,
write("I will continue here"),
...

"foreach" constructions can also be nested properly:

…,
foreach p_nd(X) do
   foreach q_nd(X, Q) do
       writef("Q = %, ", Q)
   end foreach,
   foreach r_nd(X, R) do
       writef("R = %, ", R)
   end foreach,
   writef("\nThat was for X = %\n", X)
end foreach
...

List Comprehension

Visual Prolog 7.0 introduces a new syntax and improved functionality as a supplement to findall/3.

..., List = [ A || p_nd(A) ], ...

The line above corresponds to this:

..., findall(A, p_nd(A), List), ...

The new construction is a value, and can be used as such:

..., ppp( [ A || p_nd(A) ] ), ...

The functionality has been improved so that you can calculate the values to collect:

..., List = [ pair(A, math::sin(A)) || p_nd(A)  ], ...

You can also have more calls in the "body":

..., List = [ R  || p_nd(A), S = math::sin(A), R = pair(A, S)  ], ...

Stronger Type System with Regards to Subtyping

Domain declarations like this:

domains
    myType = someType.

will define a sub-type (unless someType is a compound domain or a predicate domain) rather than a synonym type.

Values of type "myType" can automatically be used as type "someType", but a value of type "someType" will have to be explicitly converted to type "myType".

The purpose of this is to increase the safety of your programs.  Consider this little setup:

domains
    styleFlag = integer.
    color = integer.
predicates
    createWindow : (..., styleFlag Style, color Color).

"..." is meant as an abbreviation of a number of other arguments.  If "styleFlag" is synonym to "integer", and "color" is also synonym to "integer", then "styleFlag" and "color" are also synonym to each other.  Therefore a bogus call like this:

clauses
    ppp(...) :-
        Color = getColor(),
        StyleFlag = getStyleFlag(),
        createWindow(..., Color, StyleFlag). % bogus

is legal.  This is no longer the case: a "color" cannot be used as a "styleFlag" (and vice versa), unless you explicitly convert it.

Stronger Treatment of Numerical Types

One very noticeable consequence of this change is that integer and unsigned are kept much stricter apart from each other.  If you have an integer but need an unsigned, you will have to convert it explicitly.

Backwards Compatibility Issues

The following new keywords have been introduced:

if  then  else  foreach  do

This means that they can no longer be used as identifiers (Visual Prolog version 6.2 and 6.3 give a warning about this).

The stronger treatment of types might require some changes in your program.  Typically change of declarations or insertions of explicit conversions.

See also:

 

Home | Company | News | Products Downloads | Shop | Support | Visual Prolog Features | Visual Prolog Compiler | FAQ | Tutorials | Examples | Knowledge Base | Discussion Forum | wiki | Site Map
 

Prolog Development Center A/S - H.J. Holst Vej 3-5C - 2605 Broendby, Denmark - Tel +45 3636 0000 - Fax +45 3636 0001 - sales@visual-prolog.com