Being new to prolog I am reading existing code (as well as trying to write some code). Having some prior background in semweb I started to play with it and see something that is confusing me. Example assertion:
?- rdf_assert(ex:bob, rdf:type, foaf:'Person').
I also did find the following in the documentation:
Remember: Internally, all resources are atoms. The transformations
above are realised at compile-time using rules for goal_expansion/2
provided by the rdf_db library
Am I correct in assuming that somehow the library is treating the three URIs as atoms? I thought that the compiler would treat this as module_name:predicate, but that does not seem to be the case. If that is true, could you please provide a simple example on how this could be done in prolog?
Thanks
Prolog is not a functional language. This implies 2+3 does not evaluate to 5 and is just a term that gets meaning from the predicate that processes it. Likewise, ex:bob is just a term that has no direct relations to modules or
predicates. Only predicates such call/1 will interpret this as "call bob in the module ex".
Next to that, (SWI-)Prolog (most Prolog's, but not all) have term expansion that allows you to rewrite the term that is read before it is handed to the compiler. That is used to rewrite the argument of rdf/3: each appearance of prefix:local is expanded to a full atom. You can check that by using listing/1 on predicates that call rdf/3 using the prefix notation.
See also rdf_meta
Related
From reading the manual, I can't seem to find the difference between the two.
The manual says:
It is advised to use retractall/1 for erasing all clauses of a dynamic predicate.
So I chose to use retractall/1 in my program; however, I wonder what the difference is.
The retractall/1 standard built-in predicate can be used to remove all clauses for a dynamic predicate but the predicate will still be known by the runtime. The abolish/1 standard built-in predicate, in the other hand, not only removes all predicate clauses but also makes the predicate unknown to the runtime. If you try to call a dynamic predicate after removing all its clauses using retractall/1, the call simply fails. But if you abolish a dynamic predicate, calling it after will result in a predicate existence error.
In analogy to SQL:
retractall(table_name(_,_,_)) could be delete from table_name, while
abolish(table_name/3) would play as drop table_name
Before I read your question and #PauloMoura's fine answer, I didn't know the answer either.
With this answer I don't want to copy Paulo's answer. Instead, I suggest you consider reading/searching alternative Prolog-related sources:
The ISO directives, control constructs and builtins—iso-prolog on SO
4.12.5 Removing Clauses from the Database—sicstus-prolog manual
8.7 Dynamic clause management—gnu-prolog manual
Chapter 9 Dynamic Clauses and Global Variables—bprolog manual
6.14 Asserting, Retracting, and Other Database Modifications—xsb manual
6.10.1 Modification of the Data Base—part of the yap manual
Note that the above may or may not directly fit the Prolog system you use.
Still, having multiple sources is a good thing: It can keep you from getting stuck!
Is there a workaround to make ensure_loaded/1 work
in GNU Prolog as it works in many other Prolog systems?
The goal is to have a preamble so that the rest of
code can use ensure_loaded/1 independent of whether which
Prolog system I use.
I tried the following:
:- multifile(term_expansion/2).
term_expansion((:- ensure_loaded(X)),
(:- atom_concat('<base>\\', X, Y),
include(Y))).
But the following query doesn't work:
:- ensure_loaded('suite.p').
The path calculation itself is not the issue of the question,
but the redefinition of a directive in GNU Prolog. There is
another directive that causes problems: meta_predicate/1. The
byte code crashes as follows:
Bye
A partial solution is:
ensure_loaded(File) :-
absolute_file_name(File, Path),
( predicate_property(_, prolog_file(Path)) ->
true
; consult(Path)
).
It assumes that the file defines at least one predicate but that's a sensible assumption. However, there's seems to be no way to override the native, non-functional, definition of the ensure_loaded/1 directive. A workaround would be to wrap the ensure_loaded/1 directive within an initialization/1 directive. For example:
:- initialization(ensure_loaded('suite.pl')).
Hence this being a partial solution as we're really defining an ensure_loaded/1 predicate, not a directive.
My current speculation is, that it is impossible with
the standard distribution of GNU Prolog 1.4.4. The
docu says:
The GNU Prolog compiler (section 4.4) automatically calls
expand_term/2 on each Term1 read in. However, in the current release,
only DCG transformation are done by the compiler (i.e.
term_expansion/2 cannot be used). To use term_expansion/2, it is
necessary to call expand_term/2 explicitly.
I also tried to inject some Prolog code for term_expansion/2
via the command line, but to no awail. Although the tool chain
has options such as -O, -L, -A that pass options to other tools.
There is not really an option that passes a Prolog text to the
pl2wam, in course of the execution of a consult/1 issued inside
the top-level.
At least this are my results so far.
Bye
The documentation says that
copy_term(+Term, -Copy, -Body) makes a copy of Term in which all
variables have been replaced by new variables that occur nowhere
outside the newly created term. If Term contains attributed
variables, Body is unified with a term such that executing Body
will reinstate equivalent attributes on the variables in Copy.
I'm previously affirming numerical CLP(R) constraints over some variables, and at some point I collect these constraints using copy_term/3. Later, when I try to reinstate the constraints using 'call(Body)', I get an "Instantiation error" in arguments of the form [nfr:resubmit_eq(...)]
Here's a simplified example that demonstrates the problem:
:-use_module(library(clpr)).
{Old>=0, A>=0,A=<10, NR= Old+Z, Z=Old*(A/D)}, copy_term(Old,New,CTR), call(CTR).
Results in:
Instantiation error in argument 1 of '.'/2
! goal: [nfr:resubmit_eq([v(-1.0,[_90^ -1,_95^1,_100^1]),v(1.0,[_113^1])])]
My question is: how do I reinstate the constraints in Body over New? I haven't been able to find concrete examples.
copy_term/3 is a relatively new built-in predicate, that has been first introduced in SICStus about 2006. Its motivation was to replace the semantically cumbersome call_residue/2 which originated from SICStus 0.6 of 1987 by a cleaner and more efficient interface that splits the functionality in two:
call_residue_vars(Goal, Vars) which is like call(Goal) and upon success unifies Vars with a list variables (in unspecified order) that are attached to constraints and have been created or affected in Goal.
copy_term(Term, Copy, Body) like copy_term/2 and upon success unifies Body with a term to reinstate the actual constraints involved. Originally, Body was a goal that could be executed directly. Many systems that adopted this interface (like SWI, YAP) however, switched to use a list of goals instead. This simplifies frequent operations since you have less defaultyness, but at the expense of making reinstating more complex. You need to use maplist(call,Goals).
Most of the time, these two built-in predicates will be used together. You are using only one which makes me a bit suspicious. You first need to figure out which variables are involved, and only then you can copy them. Typically you will use call_residue_vars/2 for that. If you are copying only a couple of variables (as in your exemple) you are effectively projecting the constraints on these variables. This may or may not be your intention.
This is simply a bug in CLPR, which is unsupported. We lost touch with the CLPR supplier a long time ago.
In many Prolog systems it is easy to add a new search path for consulting file.
In Yap for example, the predicate I know it is add_to_path(NewPath).
Is there a way to do the same in SWI Prolog ?. My question is specifically about adding one path to the already existing paths, I am aware of the file_search_path/2 predicate for declaring directories, and the cd/1 predicate for changing the current directory, but I would like to know if there is an alternative method, like the one I found in Yap.
thanks in advance !
There are several mechanisms to this. The first one I met was in C-Prolog, which indeed used clauses for library_directory/1. The current SWI-Prolog mechanism is derived from Quintus and also used in SICStus. It generalises from the library_directory/1 approach
be treating expressions of the form <alias>(Path) as a search over the path-alias <alias>.
Paths for an alias are defined using the predicate file_search_path/2. Now, library is just an alias. Normally, libraries are added using a clause file_search_path(library, Dir).
This mechanism has proven to be pretty flexible. Of course, it would be nice if Prolog systems get more compatible here. I think todays YAP also supports the file_search_path system. (2016 Edit: It does indeed, see YAP Prolog User's Manual: Changing the Compiler’s Behavior)
In your .plrc/.yaprc/.sicstusrc/.swiplrc:
:- multifile(library_directory/1).
library_directory('/home/ulrich/lftp/Prolog-inedit').
I'm interfacing with WordNet, and some of the terms I'd like to classify (various proper names) are capitalised in the database, but the input I get may not be capitalised properly. My initial idea here is to write a predicate that produces the various capitalisations possible of an input, but I'm not sure how to go about it.
Does anyone have an idea how to go about this, or even better, a more efficient way to achieve what I would like to do?
It depends on what Prolog implementation you're using, but there may be library functions you can use.
e.g. from the SWI-Prolog reference manual:
4.22.1 Case conversion
There is nothing in the Prolog standard for converting case in textual data. The SWI-Prolog
predicates code_type/2 and char_type/2 can be used to test and convert individual
characters. We have started some additional support:
downcase_atom(+AnyCase, -LowerCase)
Converts the characters of AnyCase into lowercase as char_type/2 does (i.e. based on the
defined locale if Prolog provides locale support on the hosting platform) and unifies the
lowercase atom with LowerCase.
upcase_atom(+AnyCase, -UpperCase)
Converts, similar to downcase_atom/2, an atom to upper-case.
Since this just downcases whatever's passed to it, you can easily write a simple predicate to sanitise every input before doing any analysis.