|
View:
New views
10 Messages
—
Rating Filter:
Alert me
|
|
|
splitting facts and predicates between filesHello,
I am looking for the correct way to split the declarations of facts and predicates between a module file and fact files. The program that I write deals with a series of facts. These facts should be declared in separate files. On top of these facts there are some predicates. These predicates should be declared in a common file, like a module. For example, suppose that the facts are object/1 and consists/2. A fact file would be something like: object(foo). object(goo). object(zoo). consists(foo, goo). consists(goo, zoo). The common module includes predicates like inside/2, which means that one object is inside another: inside(X, Y) :- object(X), object(Y), consists(X,Y). inside(X, Y) :- inside(X, Z), object(Y), consists(Z, Y). I would like to load the common module and then one or more fact files, and then to have answers to queries such as "inside(A, zoo).". What should be the module declaration? Should I also use other predicate properties, such as multifile, discontiguous, module_transparent? I couldn't find a good example for this scenario. On a different note: I am currently developing an interesting application in Prolog (I hope to publish it some day!) and I find this mailing list invaluable. Thanks! Guy Wiener. _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: splitting facts and predicates between filesOn 2009/09/10, at 10:27, Guy Wiener wrote: > Hello, > > I am looking for the correct way to split the declarations of facts > and predicates between a module file and fact files. > > > The program that I write deals with a series of facts. These facts > should be declared in separate files. On top of these facts there > are some predicates. These predicates should be declared in a common > file, like a module. > > > For example, suppose that the facts are object/1 and consists/2. A > fact file would be something like: > > object(foo). > > object(goo). > > object(zoo). > > consists(foo, goo). > > consists(goo, zoo). > > > The common module includes predicates like inside/2, which means > that one object is inside another: > > inside(X, Y) :- > > object(X), > > object(Y), > > consists(X,Y). > > inside(X, Y) :- > > inside(X, Z), > > object(Y), > > consists(Z, Y). > > > I would like to load the common module and then one or more fact > files, and then to have answers to queries such as "inside(A, zoo).". > > What should be the module declaration? Should I also use other > predicate properties, such as multifile, discontiguous, > module_transparent? I couldn't find a good example for this scenario. In Logtalk you could write something like: :- object(common). :- public([object/1, consists/2, inside/2]). inside(X, Y) :- ::object(X), ::object(Y), ::consists(X, Y). inside(X, Y) :- inside(X, Z), object(Y), ::consists(Z, Y). :- end_object. :- object(facts, extends(common)). object(foo). object(goo). object(zoo). consists(foo, goo). consists(goo, zoo). :- end_object. This solution allows to load into memory any number of facts "files" you want. Simply copy the two Logtalk objects above to a source file, say, "objects.lgt", and try: % swilgt ... | ?- {objects}. ... | ?- facts::inside(A, zoo). ... You may create a source file per Logtalk object if you prefer. E.g. "common.lgt" and "facts.lgt": | ?- {common, facts}. Hope this helps. Cheers, Paulo ----------------------------------------------------------------- Paulo Jorge Lopes de Moura, PhD Assistant Professor Dep. of Computer Science, University of Beira Interior 6201-001 Covilhã, Portugal Office 3.18 Ext. 3276 Phone: +351 275319891 Fax: +351 275319899 Email: <mailto:pmoura@...> Home page: <http://www.di.ubi.pt/~pmoura> Research: <http://logtalk.org/> Blog: <http://blog.logtalk.org/> ----------------------------------------------------------------- _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: splitting facts and predicates between filesYou will probably want to use multifile/1. dynamic/1 is optional, it depends whether you want to assert new facts at runtime. For saving facts to a file you could use clause/2 to find all unit-clauses, or you could use a metamodel predicate to declare a predicates to be facts. Implicit in what you have below is a constraint that a predicate is either a fact/unit clause or a rule but never a mixture? It would be nice to see some kind of standard library for this emerge. Some (slightly vague) requirements - lightweight, and allows the user to avoid repeating him/herself - it should play nicely with modules - provide predicates such as load_facts, write_facts, etc - optional typing info on the fact arguments, all the way up to sql- style constraints e.g. :- fact(consists(object,object)) - some kind of hook into pldoc. E.g. it might be nice to write % consists(Part:object, Whole:object) and have everything else taken care of. The dbmeta module in blip (http://blipkit.org) was written to satisfy some of these requirements. I would not recommend using this outright though, I wrote it a while ago and it's acquired a lot of cruft. May be a useful source of ideas though. On Sep 10, 2009, at 2:27 AM, Guy Wiener wrote: > Hello, > > I am looking for the correct way to split the declarations of facts > and predicates between a module file and fact files. > > > The program that I write deals with a series of facts. These facts > should be declared in separate files. On top of these facts there > are some predicates. These predicates should be declared in a common > file, like a module. > > > For example, suppose that the facts are object/1 and consists/2. A > fact file would be something like: > > object(foo). > > object(goo). > > object(zoo). > > consists(foo, goo). > > consists(goo, zoo). > > > The common module includes predicates like inside/2, which means > that one object is inside another: > > inside(X, Y) :- > > object(X), > > object(Y), > > consists(X,Y). > > inside(X, Y) :- > > inside(X, Z), > > object(Y), > > consists(Z, Y). > > > I would like to load the common module and then one or more fact > files, and then to have answers to queries such as "inside(A, zoo).". > > What should be the module declaration? Should I also use other > predicate properties, such as multifile, discontiguous, > module_transparent? I couldn't find a good example for this scenario. > > > On a different note: I am currently developing an interesting > application in Prolog (I hope to publish it some day!) and I find > this mailing list invaluable. Thanks! > > > Guy Wiener. > > _______________________________________________ > SWI-Prolog mailing list > SWI-Prolog@... > https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog > _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: splitting facts and predicates between filesThanks! But, is having only predicates that are either facts or rules a
true constraints? I thing I might have to use a mix of both. Guy. Chris Mungall wrote: > > You will probably want to use multifile/1. dynamic/1 is optional, it > depends whether you want to assert new facts at runtime. For saving > facts to a file you could use clause/2 to find all unit-clauses, or > you could use a metamodel predicate to declare a predicates to be > facts. Implicit in what you have below is a constraint that a > predicate is either a fact/unit clause or a rule but never a mixture? > > It would be nice to see some kind of standard library for this emerge. > Some (slightly vague) requirements > > - lightweight, and allows the user to avoid repeating him/herself > - it should play nicely with modules > - provide predicates such as load_facts, write_facts, etc > - optional typing info on the fact arguments, all the way up to > sql-style constraints > e.g. :- fact(consists(object,object)) > - some kind of hook into pldoc. > E.g. it might be nice to write > % consists(Part:object, Whole:object) > and have everything else taken care of. > > The dbmeta module in blip (http://blipkit.org) was written to satisfy > some of these requirements. I would not recommend using this outright > though, I wrote it a while ago and it's acquired a lot of cruft. May > be a useful source of ideas though. > > On Sep 10, 2009, at 2:27 AM, Guy Wiener wrote: > >> Hello, >> >> I am looking for the correct way to split the declarations of facts >> and predicates between a module file and fact files. >> >> >> The program that I write deals with a series of facts. These facts >> should be declared in separate files. On top of these facts there are >> some predicates. These predicates should be declared in a common >> file, like a module. >> >> >> For example, suppose that the facts are object/1 and consists/2. A >> fact file would be something like: >> >> object(foo). >> >> object(goo). >> >> object(zoo). >> >> consists(foo, goo). >> >> consists(goo, zoo). >> >> >> The common module includes predicates like inside/2, which means that >> one object is inside another: >> >> inside(X, Y) :- >> >> object(X), >> >> object(Y), >> >> consists(X,Y). >> >> inside(X, Y) :- >> >> inside(X, Z), >> >> object(Y), >> >> consists(Z, Y). >> >> >> I would like to load the common module and then one or more fact >> files, and then to have answers to queries such as "inside(A, zoo).". >> >> What should be the module declaration? Should I also use other >> predicate properties, such as multifile, discontiguous, >> module_transparent? I couldn't find a good example for this scenario. >> >> >> On a different note: I am currently developing an interesting >> application in Prolog (I hope to publish it some day!) and I find >> this mailing list invaluable. Thanks! >> >> >> Guy Wiener. >> >> _______________________________________________ >> SWI-Prolog mailing list >> SWI-Prolog@... >> https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog >> > > _______________________________________________ > SWI-Prolog mailing list > SWI-Prolog@... > https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: splitting facts and predicates between filesMixing should be fine. For your purposes it may be sufficient to
declare your predicate as multifile and then just load the module and fact files using normal prolog predicates such as use_module/1 and consult/1. qcompile/1 is useful for large factfiles. Beware that multifile/1 acts a little differently in different prolog systems. On Sep 10, 2009, at 12:28 PM, Guy Wiener wrote: > Thanks! But, is having only predicates that are either facts or > rules a true constraints? > I thing I might have to use a mix of both. > > Guy. > > Chris Mungall wrote: >> >> You will probably want to use multifile/1. dynamic/1 is optional, >> it depends whether you want to assert new facts at runtime. For >> saving facts to a file you could use clause/2 to find all unit- >> clauses, or you could use a metamodel predicate to declare a >> predicates to be facts. Implicit in what you have below is a >> constraint that a predicate is either a fact/unit clause or a rule >> but never a mixture? >> >> It would be nice to see some kind of standard library for this >> emerge. Some (slightly vague) requirements >> >> - lightweight, and allows the user to avoid repeating him/herself >> - it should play nicely with modules >> - provide predicates such as load_facts, write_facts, etc >> - optional typing info on the fact arguments, all the way up to sql- >> style constraints >> e.g. :- fact(consists(object,object)) >> - some kind of hook into pldoc. >> E.g. it might be nice to write >> % consists(Part:object, Whole:object) >> and have everything else taken care of. >> >> The dbmeta module in blip (http://blipkit.org) was written to >> satisfy some of these requirements. I would not recommend using >> this outright though, I wrote it a while ago and it's acquired a >> lot of cruft. May be a useful source of ideas though. >> >> On Sep 10, 2009, at 2:27 AM, Guy Wiener wrote: >> >>> Hello, >>> >>> I am looking for the correct way to split the declarations of >>> facts and predicates between a module file and fact files. >>> >>> >>> The program that I write deals with a series of facts. These facts >>> should be declared in separate files. On top of these facts there >>> are some predicates. These predicates should be declared in a >>> common file, like a module. >>> >>> >>> For example, suppose that the facts are object/1 and consists/2. A >>> fact file would be something like: >>> >>> object(foo). >>> >>> object(goo). >>> >>> object(zoo). >>> >>> consists(foo, goo). >>> >>> consists(goo, zoo). >>> >>> >>> The common module includes predicates like inside/2, which means >>> that one object is inside another: >>> >>> inside(X, Y) :- >>> >>> object(X), >>> >>> object(Y), >>> >>> consists(X,Y). >>> >>> inside(X, Y) :- >>> >>> inside(X, Z), >>> >>> object(Y), >>> >>> consists(Z, Y). >>> >>> >>> I would like to load the common module and then one or more fact >>> files, and then to have answers to queries such as "inside(A, >>> zoo).". >>> >>> What should be the module declaration? Should I also use other >>> predicate properties, such as multifile, discontiguous, >>> module_transparent? I couldn't find a good example for this >>> scenario. >>> >>> >>> On a different note: I am currently developing an interesting >>> application in Prolog (I hope to publish it some day!) and I find >>> this mailing list invaluable. Thanks! >>> >>> >>> Guy Wiener. >>> >>> _______________________________________________ >>> SWI-Prolog mailing list >>> SWI-Prolog@... >>> https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog >>> >> >> _______________________________________________ >> SWI-Prolog mailing list >> SWI-Prolog@... >> https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog > > _______________________________________________ > SWI-Prolog mailing list > SWI-Prolog@... > https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog > _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: splitting facts and predicates between filesPaulo Moura schrieb:
> > On 2009/09/10, at 10:27, Guy Wiener wrote: > >> Hello, >> >> I am looking for the correct way to split the declarations of facts >> and predicates between a module file and fact files. ... >> I would like to load the common module and then one or more fact >> files, and then to have answers to queries such as "inside(A, zoo).". >> ... > > In Logtalk you could write something like: ... > | ?- facts::inside(A, zoo). Hi Paulo, hi Guy, the LogTalk solution is elegant but Guy asked for a solution where he could simply query "?-inside(A, zoo)", without explicitly addressing one of the different fact files. That would need a message addressed to a variable receiver, such as ?- AnyObject::inside(A, zoo). Is that legal in LogTalk? I gueess it is. If not, or if Guy was looking for a solution that runs in plain SWI Prolog without the LogTalk extension, here is a quite straightforward rewrite of Paulos solution that achieves both. Günter PS: The code below contains two modifications not related to the translation from LogTalk: - moved recursive call of "inside" to the of the clause to assure termination - renamed "object" to "obj" since "object" collides with the predicate defined in PCE. %-------------------------- File "common.pl" ---------------------- /** LogTalk2SWI translation scheme: Copied Paulos Logtalk code and replaced - the "object" declarations by "module/2" declarations, - the "public" declarations by module export, - the object extension declaration by "use_module/1" and - the :: operator by normal module qualifier and the use of "context_module/1". For all this to work as intended one must declare the "inheritable" predicates of the module "common" as "module_transparent". This illustrates a simple idiom for OO programming in SWI-Prolog. [Or better say "object-based" programming since we are simulating class-less objects that delegate to each other (no classes and no class-based inheritance). "Self" is the archetype of such languages.] **/ :- module(common, [inside/2]). :- module_transparent inside/2. % Enforce dynamic binding of "context module" inside(X, Y) :- context_module(M), M:obj(X), M:obj(Y), M:consists(X, Y). inside(X, Y) :- context_module(M), M:obj(Y), M:consists(Z, Y), inside(X, Z). %-------------------------- File facts1.pl" ---------------------- :- module(facts1, []). :- consult(common). obj(foo). obj(goo). obj(zoo). consists(foo, goo). consists(goo, zoo). %-------------------------- File "facts2.pl" ---------------------- :- module(facts2,[]). :- consult(common). obj(foo2). obj(goo2). obj(zoo). consists(foo2, goo2). consists(goo2, zoo). %-------------------------- Try in the console ------------------------ :- consult(facts1). :- consult(facts2). % Call to a specific module: ?- facts1:inside(A, zoo). % Call to any module that might possibly contribute a solution: ?- current_predicate(Module:inside(_,_)), Module:catch(inside(A, zoo),_,fail). % <-- the "catch" is essential to skip modules % in which some predicate is not defined. SWI-Prlog % would otherwise abort the goal because of an % "Undefined procedure" error even if there are % other modules left in which the goal will succeed. -------------------------------------------------------------------- Dr. Günter Kniesel http://www.cs.uni-bonn.de/~gk/ Institut für Informatik III gk@... Universität Bonn Römerstr. 164 (Raum A107) Tel (+49 228) 73-4511 D-53117 Bonn Fax (+49 228) 73-4382 _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: splitting facts and predicates between filesOn 2009/09/18, at 14:52, Günter Kniesel wrote: > Paulo Moura schrieb: >> On 2009/09/10, at 10:27, Guy Wiener wrote: >>> Hello, >>> >>> I am looking for the correct way to split the declarations of >>> facts and predicates between a module file and fact files. > ... >>> I would like to load the common module and then one or more fact >>> files, and then to have answers to queries such as "inside(A, >>> zoo).". >>> > ... >> In Logtalk you could write something like: > ... >> | ?- facts::inside(A, zoo). > > Hi Paulo, hi Guy, > > the LogTalk solution is elegant but Guy asked for a solution where > he could simply query "?-inside(A, zoo)", without explicitly > addressing one of the different fact files. Logtalk, not LogTalk. Please leave CamelCase to Java programmers ;-) Your solution below also doesn't seem to support the simply query "?- inside(A, zoo)", without explicitly addressing one of the different fact files. > That would need a > message addressed to a variable receiver, such as > > ?- AnyObject::inside(A, zoo). > > Is that legal in LogTalk? I gueess it is. No. You may, however, enumerate by backtracking all the objects that accept the inside/2 message to get the same functionality. For example: | ?- extends_object(Object, common), Object::inside(A, zoo). This is basically the same solution (based on reflection built-in predicates) that you use below with modules. You could also write: | ?- current_object(Object), Object::current_predicate(inside/1), Object::inside(A, zoo). > If not, or if Guy was looking for a solution that runs in plain > SWI Prolog without the LogTalk extension, here is a quite > straightforward rewrite of Paulos solution that achieves both. > > Günter > > PS: The code below contains two modifications not related to the > translation from LogTalk: > - moved recursive call of "inside" to the of the clause to > assure termination > - renamed "object" to "obj" since "object" collides with the > predicate defined in PCE. > > %-------------------------- File "common.pl" ---------------------- > > /** LogTalk2SWI translation scheme: Copied Paulos Logtalk code and > replaced > - the "object" declarations by "module/2" declarations, > - the "public" declarations by module export, > - the object extension declaration by "use_module/1" and > - the :: operator by normal module qualifier and the use of > "context_module/1". > For all this to work as intended one must declare the "inheritable" > predicates of the module "common" as "module_transparent". I believe that the legacy (?) directive module_transparent/1 should be avoided. New code should preferably use the standard directive meta_predicate/1. > This illustrates a simple idiom for OO programming in SWI-Prolog. > [Or better say "object-based" programming since we are simulating > class-less objects that delegate to each other (no classes and no > class-based inheritance). "Self" is the archetype of such languages.] Logtalk supports both classes and prototypes (Self is a prototype- based OOP language). Btw, the solution I posted uses prototypes, not classes (the source of the misunderstanding might be that Java uses a "extends" keyword for class specialization where Logtalk uses "extends" for parent-prototype relations and "specializes" for class specialization). > **/ > > > :- module(common, [inside/2]). > > :- module_transparent inside/2. % Enforce dynamic binding of > "context module" > ... > %-------------------------- Try in the console > ------------------------ > > :- consult(facts1). > :- consult(facts2). > > % Call to a specific module: > ?- facts1:inside(A, zoo). > > % Call to any module that might possibly contribute a solution: > ?- current_predicate(Module:inside(_,_)), > Module:catch(inside(A, zoo),_,fail). > > % <-- the "catch" is essential to skip modules > % in which some predicate is not defined. SWI-Prlog > % would otherwise abort the goal because of an > % "Undefined procedure" error even if there are > % other modules left in which the goal will succeed. The catch/3 wrapper results from a lack of distinction between declaring a predicate and defining a predicate. No such issue in Logtalk where calls to declared but not defined predicates simply fail (think closed-world assumption). I tried to extend your code by writing a new module, "root": :- module(root, [outside/2]). :- module_transparent outside/2. % Enforce dynamic binding of "context module" outside(X, Y) :- context_module(M), M:obj(X), M:obj(Y), M:consists(Y, X). outside(X, Y) :- context_module(M), M:obj(Y), M:consists(Y, Z), outside(Z, X). and then modifying the module "common" to "inherit" from the module "root": :- module(common, [inside/2]). :- consult(root). ... However, this doesn't seem to work as desired: ?- [facts1, facts2]. % root compiled into root 0.00 sec, 1,148 bytes % common compiled into common 0.00 sec, 2,352 bytes % facts1 compiled into facts1 0.00 sec, 3,780 bytes % root compiled into root 0.00 sec, 0 bytes % common compiled into common 0.00 sec, 564 bytes % facts2 compiled into facts2 0.00 sec, 1,692 bytes true. ?- facts1:outside(X, Y). Correct to: "root:outside(X, Y)"? no ERROR: '$execute_goal2'/2: Undefined procedure: facts1:outside/2 ?- facts1:outside(X, Y). Correct to: "root:outside(X, Y)"? yes ERROR: root:outside/2: Undefined procedure: root:obj/1 ^ Exception: (7) root:outside(_G230, _G231) ? creep Do you think it's possible to simulate inheritance in a "module hierarchy" that is more than two levels deep? Cheers, Paulo ----------------------------------------------------------------- Paulo Jorge Lopes de Moura, PhD Assistant Professor Dep. of Computer Science, University of Beira Interior 6201-001 Covilhã, Portugal Office 3.18 Ext. 3276 Phone: +351 275319891 Fax: +351 275319899 Email: <mailto:pmoura@...> Home page: <http://www.di.ubi.pt/~pmoura> Research: <http://logtalk.org/> Blog: <http://blog.logtalk.org/> ----------------------------------------------------------------- _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
OOP in SWI (was: splitting facts and predicates between files)Hi Paulo,
thanks for your quick reply and sorry for letting you wait. Paulo Moura wrote: > Logtalk, not LogTalk. Please leave CamelCase to Java programmers ;-) Sorry. I'll remember that it's like Smalltalk ;) > Your solution below also doesn't seem to support the simply query > "?-inside(A, zoo)", without explicitly addressing one of the different > fact files. It does. Please note that in the query ?- current_predicate(_, Module:inside(_,_)), Module:catch(inside(A, zoo),_,fail). the "Module" is a free variable. So you don't need to know all the objects in advance but can simply ask the query and get back the results AND the objects that provide them. > This is basically the same solution (based on reflection built-in > predicates) that you use below with modules. You could also write: > > | ?- current_object(Object), Object::current_predicate(inside/1), > Object::inside(A, zoo). This indeed looks pretty much equivalent to the above two lines of SWI code. >> This illustrates a simple idiom for OO programming in SWI-Prolog. >> [Or better say "object-based" programming since we are simulating >> class-less objects that delegate to each other (no classes and no >> class-based inheritance). "Self" is the archetype of such languages.] > > Logtalk supports both classes and prototypes (Self is a prototype-based > OOP language). Btw, the solution I posted uses prototypes, not classes > (the source of the misunderstanding might be that Java uses a "extends" > keyword for class specialization where Logtalk uses "extends" for > parent-prototype relations and "specializes" for class specialization). the simulation that I suggested -- which is definitely object-based (or prototype-based if you prefer the term). >> % Call to any module that might possibly contribute a solution: >> ?- current_predicate(Module:inside(_,_)), >> Module:catch(inside(A, zoo),_,fail). >> >> % <-- the "catch" is essential to skip modules >> % in which some predicate is not defined. SWI-Prlog >> % would otherwise abort the goal because of an >> % "Undefined procedure" error even if there are >> % other modules left in which the goal will succeed. > > The catch/3 wrapper results from a lack of distinction between declaring > a predicate and defining a predicate. No such issue in Logtalk where > calls to declared but not defined predicates simply fail (think > closed-world assumption). predicate is undeclared AND when it is undefined). However, different applications have different requirements so ideally there should be an option to control whether it fails or whether it trows an exception. > I tried to extend your code by writing a new module, "root": > > :- module(root, [outside/2]). > > :- module_transparent outside/2. % Enforce dynamic binding of "context > module" > > outside(X, Y) :- context_module(M), > M:obj(X), > M:obj(Y), > M:consists(Y, X). > outside(X, Y) :- context_module(M), > M:obj(Y), > M:consists(Y, Z), > outside(Z, X). > > and then modifying the module "common" to "inherit" from the module "root": > > :- module(common, [inside/2]). > :- consult(root). > ... > > However, this doesn't seem to work as desired: > Do you think it's possible to simulate inheritance in a "module > hierarchy" that is more than two levels deep? Sure. Simply add the inherited predicates to the export list of the inheriting module if you want them to be inherited by its children. In your example simply modify :- module(common, [inside/2]). to :- module(common, [inside/2, outside/2]). I've attached a zip file with the complete example including the results of the goals we discussed. Regards, Günter |
|
|
Re: OOP in SWI (was: splitting facts and predicates between files)On 2009/09/22, at 19:21, Günter Kniesel wrote: > Hi Paulo, > > thanks for your quick reply and sorry for letting you wait. > > Paulo Moura wrote: > >> Logtalk, not LogTalk. Please leave CamelCase to Java programmers ;-) > > Sorry. I'll remember that it's like Smalltalk ;) > >> Your solution below also doesn't seem to support the simply query >> "?-inside(A, zoo)", without explicitly addressing one of the >> different fact files. > > It does. Please note that in the query > > ?- current_predicate(_, Module:inside(_,_)), > Module:catch(inside(A, zoo),_,fail). > > the "Module" is a free variable. So you don't need to know all the > objects in advance but can simply ask the query and get back the > results AND the objects that provide them. > >> This is basically the same solution (based on reflection built-in >> predicates) that you use below with modules. You could also write: >> | ?- current_object(Object), Object::current_predicate(inside/ >> 1), Object::inside(A, zoo). > > This indeed looks pretty much equivalent to the above two lines of > SWI code. Yes, both solutions are basically the same :-) >>> % Call to any module that might possibly contribute a solution: >>> ?- current_predicate(Module:inside(_,_)), >>> Module:catch(inside(A, zoo),_,fail). >>> >>> % <-- the "catch" is essential to skip modules >>> % in which some predicate is not defined. SWI-Prlog >>> % would otherwise abort the goal because of an >>> % "Undefined procedure" error even if there are >>> % other modules left in which the goal will succeed. >> The catch/3 wrapper results from a lack of distinction between >> declaring a predicate and defining a predicate. No such issue in >> Logtalk where calls to declared but not defined predicates simply >> fail (think closed-world assumption). > > In general, I'd prefer the goal to silently fails in both cases > (when a > predicate is undeclared AND when it is undefined). However, different > applications have different requirements so ideally there should be an > option to control whether it fails or whether it trows an exception. Making the standard Prolog flag "unknown" local to a module/object could provide such an option. >> I tried to extend your code by writing a new module, "root": >> :- module(root, [outside/2]). >> :- module_transparent outside/2. % Enforce dynamic binding of >> "context module" >> outside(X, Y) :- context_module(M), >> M:obj(X), >> M:obj(Y), >> M:consists(Y, X). >> outside(X, Y) :- context_module(M), >> M:obj(Y), >> M:consists(Y, Z), >> outside(Z, X). >> and then modifying the module "common" to "inherit" from the module >> "root": >> :- module(common, [inside/2]). >> :- consult(root). >> ... >> However, this doesn't seem to work as desired: > ... >> Do you think it's possible to simulate inheritance in a "module >> hierarchy" that is more than two levels deep? > > Sure. Simply add the inherited predicates to the export list of the > inheriting module if you want them to be inherited by its children. > > In your example simply modify > > :- module(common, [inside/2]). > to > :- module(common, [inside/2, outside/2]). > > I've attached a zip file with the complete example including the > results > of the goals we discussed. Nice, lightweight solution. Thanks for sharing :-) Cheers, Paulo ----------------------------------------------------------------- Paulo Jorge Lopes de Moura, PhD Assistant Professor Dep. of Computer Science, University of Beira Interior 6201-001 Covilhã, Portugal Office 3.18 Ext. 3276 Phone: +351 275319891 Fax: +351 275319899 Email: <mailto:pmoura@...> Home page: <http://www.di.ubi.pt/~pmoura> Research: <http://logtalk.org/> Blog: <http://blog.logtalk.org/> ----------------------------------------------------------------- _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
|
|
Re: OOP in SWIPaulo Moura schrieb:
> > On 2009/09/22, at 19:21, Günter Kniesel wrote: > >> Hi Paulo, >> >> thanks for your quick reply and sorry for letting you wait. >> >> Paulo Moura wrote: >> >>> Logtalk, not LogTalk. Please leave CamelCase to Java programmers ;-) >> >> Sorry. I'll remember that it's like Smalltalk ;) >> >>> Your solution below also doesn't seem to support the simply query >>> "?-inside(A, zoo)", without explicitly addressing one of the >>> different fact files. >> >> It does. Please note that in the query >> >> ?- current_predicate(_, Module:inside(_,_)), >> Module:catch(inside(A, zoo),_,fail). >> >> the "Module" is a free variable. So you don't need to know all the >> objects in advance but can simply ask the query and get back the >> results AND the objects that provide them. >> >>> This is basically the same solution (based on reflection built-in >>> predicates) that you use below with modules. You could also write: >>> | ?- current_object(Object), >>> Object::current_predicate(inside/1), >>> Object::inside(A, zoo). >> >> This indeed looks pretty much equivalent to the above two lines of SWI >> code. > > Yes, both solutions are basically the same :-) > >>>> % Call to any module that might possibly contribute a solution: >>>> ?- current_predicate(Module:inside(_,_)), >>>> Module:catch(inside(A, zoo),_,fail). >>>> >>>> % <-- the "catch" is essential to skip modules >>>> % in which some predicate is not defined. SWI-Prlog >>>> % would otherwise abort the goal because of an >>>> % "Undefined procedure" error even if there are >>>> % other modules left in which the goal will succeed. >>> The catch/3 wrapper results from a lack of distinction between >>> declaring a predicate and defining a predicate. No such issue in >>> Logtalk where calls to declared but not defined predicates simply >>> fail (think closed-world assumption). >> >> In general, I'd prefer the goal to silently fails in both cases (when a >> predicate is undeclared AND when it is undefined). However, different >> applications have different requirements so ideally there should be an >> option to control whether it fails or whether it trows an exception. > > Making the standard Prolog flag "unknown" local to a module/object could > provide such an option. > >>> I tried to extend your code by writing a new module, "root": >>> :- module(root, [outside/2]). >>> :- module_transparent outside/2. % Enforce dynamic binding of >>> "context module" >>> outside(X, Y) :- context_module(M), >>> M:obj(X), >>> M:obj(Y), >>> M:consists(Y, X). >>> outside(X, Y) :- context_module(M), >>> M:obj(Y), >>> M:consists(Y, Z), >>> outside(Z, X). >>> and then modifying the module "common" to "inherit" from the module >>> "root": >>> :- module(common, [inside/2]). >>> :- consult(root). >>> ... >>> However, this doesn't seem to work as desired: >> ... >>> Do you think it's possible to simulate inheritance in a "module >>> hierarchy" that is more than two levels deep? >> >> Sure. Simply add the inherited predicates to the export list of the >> inheriting module if you want them to be inherited by its children. >> >> In your example simply modify >> >> :- module(common, [inside/2]). >> to >> :- module(common, [inside/2, outside/2]). >> >> I've attached a zip file with the complete example including the results >> of the goals we discussed. > > > Nice, lightweight solution. Thanks for sharing :-) You're welcome. By the way, one could use "use_module" and "reexport/1" to make the above even a bit easier. "reexport" should avoid the need to repeat the transitively inherited predicates manually in the own export list. In the above case, one could write: :- module(common, [inside/2]). :- reexport(root). Cheers, Günter _______________________________________________ SWI-Prolog mailing list SWI-Prolog@... https://mailbox.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog |
| Free embeddable forum powered by Nabble | Forum Help |