
Hi, ----- Original Message ----- From: "Roshan" <roshan_naik@yahoo.com> To: <boost@lists.boost.org> Sent: Friday, May 07, 2010 11:38 AM Subject: Re: [boost] [castor] Interest in Logic Paradigm for C++ ?
On Wed, 05 May 2010 12:57:07 -0600, vicente.botet <vicente.botet@wanadoo.fr> wrote:
* Separation between relation structure and bindings [..snip..] 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.
This example is only introductory and too simplistic to address your valid concern. Its purpose is to demonstrate some basic concepts driving this paradigm and is used classically in teaching Prolog.
In practice, you will not hard code so many records ... you retrieve it from some database/container. Then the relation would merely return something that references the record-set with ability to perform enumeration/look-up.
The problem was that the dynamic relation example builds this tree relation. I think that the efficient alternative must be included soon on the tutorial, as otherwise people statrts to look for better implementations. Is the efficient alternative based on co-routines?
* Relation structure definition
relation_schema<string,string> father = gender(_1,"male")&& child(_2,_1);
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");
This style leads to "open ended" relations. Anybody can inject clauses into child or father...dangerous. then you need protection mechanisms. The current style ensures "closed" relations by default... which is similar to C++ functions being "closed".
A dynamic relation is not closed neither or is it?
This design is a deliberate breakaway from Prolog.
_1 , _2 have limitations on arity. relations are direct computational equivalents in LP to functions Therefore the current syntax modeled to be closer to around functions/expressions rather than data. It allows things like member relations, virtual member relations and template relations etc. Which in turn allows us to extend existing OO design patterns to the LP.
Definitely I need to read completly the documentation. Do you have some tutorials on which we see how this integration is achieved?
Also I feel the syntax
relation child = x || y || z ;
is nicer to read/type than
relation_schema<..> child; child |= x; child |= y; child |= z;
I agree for this example. I will comeback when will have a concret used case of dynamic configuration of relations.
* Bindings
Think of it in terms currying in the functional paradigm. When you take a (binary) function and bind one of its argument you still have a (unary) function. Same with relations. Don't think of a relation as data... even if the initial examples in the tutorial gives you that feeling. think of them as rules perhaps (rather than facts) ..if it helps.
I know that.
* 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.
Perhaps, but I don't think I see the motivating benefits. The syntax is getting poorer. Will need more fleshed out details with definitions of child(), father() & ancestor().
If you really like to use "range based for loops" or "iterator style enumeration" its nicer to :
for( auto res : iterable(father(x,y)) ) cout << *x << " " << *y <<"\n";
where iterable adapts an arbitrary relation/coroutine into an iterator.
I like this. Is iterable part of the library or an alternative design?
* 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?
The goal of the example is only to demonstrate how to dynamically build the clauses in a relations. You can make this example more efficient with some work. For brevity, the existing example is re-used and implemented differently. Your solution is to define the relation imperatively as opposed to adding clauses dynamically. That is a valid alternative... although it requires more work it can often lead to efficiency gains.
Can you point me to the different implementation that is efficient?
BTW: remember in your code above ... unification is not merely assignment.
I know that also. ;-)
No need for inheritance either.
Grat. I just writo : relarion as I had not found the definition of the Concept behind relation on the tutorial? is it any functions returning bool and having lref parameters?
It would roughly look as follows:
struct gender_dyn : Coroutine { gender_dyn(lref<string> p, lref<string> g);
bool operator() (void) { co_begin(); <snip> co_end(); } };
Wow, are coroutines part of the library also? or is just an alternatives design? Could you point to a complete example on the documentation? If all the utilities you have given are already on the library it is time I read completly the documentation. Thanks, Vicente _____________________ Vicente Juan Botet Escribá http://viboes.blogspot.com/