Boost logo

Boost :

Subject: Re: [boost] [castor] Interest in Logic Paradigm for C++ ?
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-05-05 14:57:07


----- Original Message -----
From: "Roshan Naik" <roshan_naik_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Thursday, April 29, 2010 9:12 AM
Subject: [boost] [castor] Interest in Logic Paradigm for C++ ?

>
> Based on suggestions from some Boost community experts, I would like to
> gauge interest to see if there is broader interest for including the Castor
> library into Boost. In short, Castor's aim is to foster multiparadigm
> programming in C++ by supporting techniques from the Logic Paradigm.

Hi, I'm interesteed,and as others I have some comments I want to share.

* Separation between relation structure and bindings

Given

// c is child of p
relation child(lref<string> c, lref <string> p) {
  return eq(c,"Sam") && eq(p,"Mary") //fact 1
    || eq(c,"Denise") && eq(p,"Mary") //fact 2
    || eq(c,"Sam") && eq(p,"Frank")//fact 3
    || eq(c,"Denise") && eq(p,"Frank")//fact 4
    || eq(c,"Frank") && eq(p,"Gary") //fact 5
    ;
}

The following code

lref<string> m,d;
relation xx= child(,"Sam", m) && child(,d, ,"Mary")

will build twice the relation generated by the function child. This should be an expensive operation if instead of 5 record child had 1000, or even more.

I don't know how this can be done in your library, but in my opinion, the relation structure and the binding should be separated, so the relation structure is shared between all the bindings.

* Relation structure definition
A relation schema could be strongly typed. Note that I have removed the lref<>, as it seems redundant

relation_schema<string,string> father = gender(_1,"male")&& child(_2,_1);

_1, _2 are placeholders to name the first and second argumentes of the relation
relation_schema<X,Y> defines the operator()(lref(X),lref(Y)) which returns a relation which will bind the arguments.

child could be defined as follows:

relation_schema <string, string> child;

child |= eq(_1,"Sam") && eq(_2,"Mary");
child |= eq(_1,"Denise") && eq(_2,"Mary") ;
child |= eq(_1,"Sam") && eq(_2,"Frank");
child |= eq(_1,"Denise") && eq(_2,"Frank");
child |= eq(_1,"Frank") && eq(_2,"Gary");

* Bindings

Concrete instances of relation could be constructed by using the operator() as before, but this time it is applied to a relarion_schema.

lref<string> c;
relation franksChildren = father("Frank", c);
while( franksChildren() ) {
  cout << *c << " is Frank's child\n";
}

Note that the code has not been changed.

* Typed relations
I'm not sure of ot is possible to implement the following, but let me continue.

The preceding example uses a type erasure to have untyped relation. Castor could also have typed relations. typed_relation<T1,...,Tn>
can be considered as a container of tuple<lref<T1>,...,lref<Tn>>

typed_relation<string,string> father_child = father(_1, _2);
for(tuple<lref<string>,lref<string> > r&: father_child) {
  lref<string> f, c;
  tie(f,c) = r;
  cout << c << " is " << f << "'s child\n";
}

or using iterators

for(typed_relation<string,string>::iterator it= father_child.begin(); it!=father_child.end();++it) {
  lref<string> f, c;
  tie(f,c) = *it;
  cout << c << " is " << f << "'s child\n";
}

There are surely a lot of errors on the preceding design, but I think is worth see if it is possible to adapt it to your library.

* dynamic relations / views
Example extracted from the tutorial

list<pair<string,string> > genderList = ...;
// dynamically building a relation
Disjunctions gender_dyn(lref<string> p, lref<string> g) {
  Disjunctions result;
  list<pair<string,string> >::iterator i;
  for( i=genderList.begin(); i!=genderList.end(); ++i)
     result.push_back(eq(p,i->first) && eq(g,i->second) );
  return result;
}

What you talk dynamic relations is a transformation from a container to a disjonction relation.
The user could implement a relation directly ensuring the unification. E.g.

struct gender_dyn : relation
 ...
 list<pair<string,string> > list_;
 list<pair<string,string> >::iterator current_;

 bool operator(lref<string> p, lref<string> g) {
   if (current_==list.end()) return false;
   p= current_->first; // unification
   g= current_->second; // unification
   ++current_;
   return true;
 }

 bool operator(string const& p, lref<string> g) {
   while (current_!=list.end() && p!=current_->first)
     ++current_;
   if (current_==list.end()) return false;
   g= current_->second; // unification
   ++current_;
   return true;
}
...

This should be more efficient, ins't it?

Do you think that something like that could be possible with your library. What will be the needed adaptations?

Best,
Vicente
_____________________
Vicente Juan Botet Escribá
http://viboes.blogspot.com/


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk