Is there a Prolog name for atom/1 or stream/1 etc (SWI-Prolog) - prolog

Just made a funny observation. SWI-Prolog allows other things than
atom as a functor in a compound. For example it allows me to do:
/* atom as functor */
?- Y =.. [foo, bar].
Y = foo(bar).
/* stream as functor */
?- current_input(X), Y =.. [X, bar].
X = <stream>(0000000069066420),
Y = <stream>(0000000069066420)(bar).
I wonder whether there is a name for what is allowed as a functor,
i.e atom or stream etc.. . The error message by SWI-Prolog doesn't
tell me what is the name, it says it expects an atom:
?- Y =.. [1, bar].
ERROR: Type error: `atom' expected, found `1' (an integer)
But as can be seen a stream etc.. , which is accepted, is not an atom:
?- current_input(X), atom(X).
false.
What is the umbrella type for what SWI-Prolog accepts as functor?
P.S. My guess why this is allowed: It is for example used for Dicts,
dicts are compounds with a special functor C'dict'.
Edit 10.09.2021:
I first thought its simple/1. But simple/1 is reserved
for atom or var, according to this answer:
What is the meaning of predicate "simple/1" in Prolog (SWI-Prolog)

In SWI-Prolog, blobs (binary large objects) are used to store arbitrary binary data, including atoms, images, and stream handles. Particularly, a blob represening a stream handle is a unique symbol which has no syntactical representation (although it is outputted as <stream>(hex-number)).
The built-in predicate blob/2 can be used to get the type of a blob:
?- X = foo, blob(X,Y).
X = foo,
Y = text.
?- current_input(X), blob(X,Y).
X = <stream>(0000000069057160),
Y = stream.
Thus, I think the type accepted as functor in SWI-Prolog is blob.

In Dogelog Runtime we recently introduced a new type tester called symbol/1. One can imagine that it is bootstrapped from blob/2 as follows:
symbol(X) :- blob(X, _).
Dogelog Runtime does also accept symbols as functors, similar like SWI-Prolog. This is used to inline disjunction and if-then-else, and could have further optimization use cases. Functors are not only restricted to atoms, they can be atoms or references:
/* Dogelog Runtime, 0.9.6 */
?- current_input(X), atom(X).
fail.
?- current_input(X), Y =.. [X, bar].
X = [object Object], Y = [object Object](bar).
But I am currently thinking about extending (=..)/2 even more. Namely to allow a compound as functor. What should a compound as functor do? Very simple:
/* Expected Result */
?- X =.. [foo(bar), baz].
X = foo(bar, baz)
So (=..)/2 would add the arguments to the given compound. This further extension of (=..)/2 doesn't need a new data type in the compound functor, but rather changes its behaviour.
It would have a couple of use cases:
Old Higher Order:
Bootstrapping apply/2 would be as easy as:
apply(X,L) :- G =.. [X|L], G.
New Higher Order:
Bottstrapping call/n would be as easy as:
call(X,Y) :- G =.. [X,Y], G.
call(X,Y,Z) :- G =.. [X,Y,Z], G.
call(X,Y,Z,T) :- G =.. [X,Y,Z,T], G.
Etc..
DCG Expansion:
Expanding a non-terminal by an input and output list would be only a matter of calling (=..)/2. Here is an example:
?- G =.. [np(X),I,O].
G = np(X,I,O).

Related

what is the difference between a predicate and a functor in prolog?

The following is an example of prolog.
likes(mary,X) :- yellow(X).
According to the definitions I've found (LPN, Bratko, AoP) the likes fits the definition of a predicate and a functor.
yellow also fits the definitions. If the clause were a simple fact (empty body), eg yellow(banana). , that would appear to make no difference.
Question: What is the difference between a predicate and a functor, in the context of prolog, if any?
functor is used to describe terms syntactically: likes(mary,X) is a term that has an arity of 2 and a primary functor likes. The functor is written likes/2 because it is a couple of a name and an arity. Note that likes/2 is also a term, written in an infix way:
?- functor(likes(a,b),F,A).
F = likes,
A = 2.
?- functor(likes/2,F,A).
F = (/),
A = 2.
An atom is a term of arity 0:
?- functor(banana, F, A).
F = banana,
A = 0.
Now, terms in Prolog can be used to describe data or to define procedures. When you write S = person(Name, Age), the functor of S is person/2, it is not ground because it contains unbound variables. By itself, it is just a data structure. However, you can also try to call it in a query:
?- S = person(Name, Age), call(S).
The above is equivalent to:
?- person(Name, Age).
But unless you defined such a predicate, you will encounter an error.
You can write predicates as follows in your source code:
person(Name, Age) :-
date_of_birth(Name, Date),
age_now(Date, Age).
The body of the clause can also be trivially true:
person(john, 20) :- true.
In which case it is a fact, also written:
person(john, 20).
See also term from The Prolog Dictionary.

Prolog - How to separate atoms from expression involving predicates?

If I’ve an expression:
x + y * (-z)
How to I separate them to form a list of [x,y,z]?
My idea:
split2(X, [X]) :-
X \= +(_,_),
*(_,_),
-(_).
split2(X + Y, [H|T]) :-
split2(X,[H]),
split2(Y, T).
(Repeat for * and -).
Somehow it only works for simple case(involving 2 terms or only one predicate), but not complicated one.
Can someone tells me what’s wrong with my idea?
Follows a solution using DCGs that doesn't require a grammar rule per arithmetic operator and that takes full advantage of first-argument indexing (thus avoiding spurious choice-points or ugly cuts in the grammar rules):
split(Expression, Atomics) :-
Expression =.. [Functor| Args],
phrase(split_atomics(Args, Functor), Atomics).
split_atomics([], Atomic) -->
[Atomic].
split_atomics([Head| Tail], _) -->
split_list([Head| Tail]).
split_list([]) -->
[].
split_list([Head| Tail]) -->
{Head =.. [Functor| Args]},
split_atomics(Args, Functor),
split_list(Tail).
Sample calls:
| ?- split((x + y * (-z)), Atomics).
Atomics = [x, y, z]
yes
| ?- split((x + 3 * (-2)), Atomics).
Atomics = [x, 3, -2]
yes
Your predicates are pretty mixed up. For starters, you're using X \= _+_ to prevent the other rule from matching; instead you should use atomic(X). You're then saying _*_, -_ which is not clearly saying anything in particular except that certain anonymous variables... exist? Anyway, the rest of the first clause is erroneous for one reason or another.
Your second clause is off to a decent start, but I think you are avoiding a use of append/3 here for no particular reason. In the head, you are expecting H to be an atom, but then with the first term in the body you're forcing H to be a singleton list. What if X = a*b? You'd expect split2(a*b,[a,b]) to unify.
You're not far from where you need to be though. This is probably your general pattern:
split2(X, [X]) :- atomic(X).
split2(-X, Result) :- split2(X, Result).
split2(X+Y, Result) :-
split2(X, XVars),
split2(Y, YVars),
append(XVars, YVars, Result).
Continue the pattern for your other operators.
Can someone tells me what's wrong with my idea?
What you are doing is too complicated, that's what's wrong. If you really have as input a valid compound term, and what you need to get out of it is a list of the atomic sub-terms, then, here is what you might want to try:
expression_atoms(E) -->
{ compound(E),
E =.. [_Name|Args]
},
!,
expression_list_atoms(Args).
expression_atoms(E) -->
{ atomic(E)
},
!,
[E].
expression_list_atoms([E|Es]) -->
expression_atoms(E),
expression_list_atoms(Es).
expression_list_atoms([]) --> [].
(Ninja edit: see the solution by Paulo Moura for a cleaner implementation of the same idea.)
The only reason why this is a DCG and not a normal predicate is that I am too lazy to figure out how to do the appends properly.
Here is a small test:
?- X = x + y * (-z).
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X).
+(x,*(y,-(z)))
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X), phrase(expression_atoms(X), Atoms).
+(x,*(y,-(z)))
X = x+y* -z,
Atoms = [x, y, z].
In the last query, you can see the atoms extracted from the expression.
As you see, this solution doesn't care about the names of the compound terms. This happens in line 3 of the listing:
E =.. [_Name|Args]
So you can throw anything at it and it will still "work":
?- phrase(expression_atoms(
the(naked, truth(about(our(waitresses))), is(that(they(only(flirt, with, you))), to(get(a(better(tip('!')))))))),
Atoms).
Atoms = [naked, waitresses, flirt, with, you, !].
If you want this to fail for anything else but a predefined list of operators with a given arity, then you'd have to put a bit more code in there.

Change name of predicate/functor in prolog

I am writing a module which uses term_expansion/2 to process a prolog source file. While doing so, I deconstruct predicates using =.. or project to its name using functor/3.
For example:
?- functor(pred(foo, bar), N, _).
N = pred.
?- pred(foo, bar) =.. L.
L = [pred, foo, bar].
Now I want to change the name of pred to (for example) pred_expanded and make it a term again, so that pred(foo, bar) becomes pred_expanded(foo, bar).
I tried append(pred, "_expanded", F) and append(pred, '_expanded', F) without success.
change_functor(Term,NewFunctor,NewTerm) :-
Term =.. [_|Args],
NewTerm =.. [NewFunctor|Args].
term_expansion(Term,ExpandedTerm) :-
functor(Term,pred,2),
change_functor(Term,pred_expanded,ExpandedTerm).
For example:
?- term_expansion(pred(foo,bar),T).
T = pred_expanded(foo, bar).
Illustrates how to use the "univ" predefined predicate. However, this is the best solution:
term_expansion(pred(A,B),pred_expanded(A,B)).
If you need to translate any functor, use atom_concat/3 as stated before:
term_expansion(Term,ExpandedTerm) :-
functor(Term,F,_),
atom_concat(F,'_expanded',NewF),
change_functor(Term,NewF,ExpandedTerm).
Example:
?- term_expansion(kk(1,2,3),N).
N = kk_expanded(1, 2, 3).

How to deconstruct a compound term in SWI Prolog

I have compound terms that can have a number inside the braces.
For example: qpowieipq(5),lsjdlasa(15) or lkjlk. I got it from the database (like my_list([rxclk,rxer,rxdv,rxd(0),rxd(1),rxd(2),crs,col,txen,txd(0),txd(1),txd(2),‌​txd(3)]).).
How can I get the value of the number inside the braces?
For example:
my_function(qpowieipq(5), X).
X=5.
my_function(lsjdlasa(15), X).
X=15.
my_function(lkjlk, X).
false
I am using SWI Prolog.
You can use (=..)/2 and pattern matching to deconstruct Prolog's compound terms. For instance
?- a =.. X.
X = [a].
?- a(1) =.. X.
X = [a, 1].
So, tentatively
my_function(T, V) :- T =.. [_,V], number(V).
This will work with any ISO compliant Prolog processor.

Prolog - deconstructing goals into individual facts and arithmetic

I'm attempting to write a small program that breaks up a given goal into all its smallest parts and eventually evaluates them. So far I have:
alien(X) :- fromMars(X), fromSaturn(X); fromJupiter(X), X = 'john'.
fromMars(john).
fromSaturn(john).
fromJupiter(john).
test(true) :- !.
test((Goal1,Goal2)) :- test(Goal1), test(Goal2).
test((Goal1;Goal2)) :- test(Goal1), test(Goal2).
test(X = Y) :- call(X = Y).
test(Goal) :- clause(Goal,Body),test(Body).
As far as I can tell so far, this will recursively inspect rules using clause/2 e.g. if I call test(alien(john)). . When it reaches the point that Body contains only facts such as fromMars(X), fromSaturn(X); fromJupiter(X), X = 'john' it will split those using the test((Goal1,Goal2)) :- and test((Goal1;Goal2)) :- rules, eventually reaching singular facts. When passed a singular fact, clause/2 will instantiate Body to true if it can be solved.
Problems arise with arithmetic. In the above program, eventually there will be the singular goal X = 'john' This causes an error with clause/2 (private procedure?). I introduced the rule test(X = Y) :- to catch this case so I can deal with it another way. However what I really want is a rule that will catch all arithmetic. Obviously I cant write a rule in the style of test(X = Y) :- to catch all possible types of arithmetic.
My goal is to eventually write an abductive meta-interpeter that can handle any type of rule thrown at it.
Let me know if none of this makes any sense and I'll try to clarify :)
meta interpreters it's one of the 'strong points' of Prolog. See this page from Markus Triska about this interesting theme.
As Little Booby Tables advised, you can capture arithmetic with something simple as
test(X is Y) :- X is Y.
BTW I think you have a typo here
test((Goal1;Goal2)) :- test(Goal1), test(Goal2).
should be
test((Goal1;Goal2)) :- test(Goal1) ; test(Goal2).
EDIT: working with operators can be generalized, if required. Just an example of the builtins required:
?- X = (1+2), X =.. [F, A, B], current_op(U, V, F).
X = 1+2,
F = (+),
A = 1,
B = 2,
U = 200,
V = fy .

Resources