Concatenate two atoms in prolog without using atom_concat - prolog

I want to write prolog that can essentially do what this is doing
atom_concat('3',' =',Answer).
Answer = '3 ='.
But I do not want to use the atom_concat function (or any built in predicates). I would also like the answer to have no quotation marks in it.
I have tried implementing a method that operates the same as the append method, which I have called merge.
merge([],Xs,Xs).
merge([X|Xs],Ys,[X|Zs]):-
merge(Xs,Ys,Zs).
But when I write this into my db.pl file I get false when running it.
?- [db].
true.
?- merge('3',' =',Answer).
false.

You can't mutate immutable values. You could use string_concat/3 to create a merger of two string atoms. By putting 'Variable' you are signalling Prolog that you want an ATOM called Variable. So numerical 3 and string atom '3' are not the same. What basically happens is you have two >immutables<, so a third has to be made that is an amalgamation of the other two.
atom_concat
string_concat
'merge' is also a deprecated method, just to clear up any confusion:
merge
The program you want:
The query
?- trace, (concat_strings(['Hello ','Hello ','Hello '],[world1,world2,world3],Output)).
The code
concat_strings([H1|T1],[H2|T2],[H3|T3]) :-
string_concat(H1, H2, H3),
concat_strings(T1,T2,T3).
concat_strings([],[],[]).
It takes the the first word of both lists, makes a new immutable atom from the 2 through string_concat and puts it in H3, which is then put onto the head of the list when the call ends. We have the end condition concat_strings([],[],[]) and the first 2 are the lists YOU pass, the third means T3 eventually unifies as T3 = [], which is also the atom to show Prolog the end of a list has been reached. Prolog then starts stepping back, adds [] as the tail and then adds the new atoms to the new list as it works its way back to your call.
OPINION:
My favorite resource for Prolog basics explained: http://www.learnprolognow.org/lpnpage.php?pageid=top

built_equality_structure(Id,Value,Id = Value).
If you call it with
?- built_equality_structure(a,3,X).
you will get the result
X = (a=3)
where the Prolog system only add parentheses for readability.

Related

Array Univ var ([x,y]=..T) - prolog

I saw a question asking what does [a,b,c]=..L. return.
When testing this I saw that it returns: L = ['.', a, [b, c]].
I can't understand why this happens, I was unable to understand the nature of Univ from the documentation. Understanding this will help me understand Univ.
One way to learn more about terms is to use write_canonical/1 in a conforming Prolog system.
For example, with GNU Prolog, we obtain:
| ?- write_canonical([x,y]).
'.'(x,'.'(y,[]))
This shows:
the primary functor in this term is '.', with arity 2
the first argument is x
the second argument is '.'(y, []), which is the list [y]
This explains why (=..)/2 yields:
| ?- [x,y] =.. Ls.
Ls = ['.',x,[y]]
and also your other example.
This happends because representation of the list in prolog is a tree datastructure,like this.It's top node is a "dot" left side is Head then again a dot on right if tail is not empty and head on left hand side and "dot" on right handside. When you do this you are simply creating a predicate(well , not exact a predicate but it is sometimes needed as i show an example): suppose i write:
V=..[somefunctor,X,Y,Z]
Then it will automatically construct a predicate like this:
somefunctor(X,Y,Z).
Now Why do we need this? Supppose i call a predicate with these terms: predicate(somefunctor,term,term2,term3) and predicate or rule looks something like this: predicate(X,Y,Z,T) and i ask you that no matter what predicate is in X, you have to call this predicate with parameters Y,Z,T. May be you think you call that predicate by writing like this: X(Y,Z,T) but unfortunately it is not allowed in prolog, so here you can use V=..[X,Y,Z,T] where X should be placed as first argument because it's predicate name and as a result you get something like this: V = somefunctor(term,term2,term3) and this happends internally. In order to invoke this predicate you make use of call predicate:
call(V) where `call/1` is a metapredicate and `V=..` is a not logical predicate.

How do i count words in prolog?

I try to count words in a string in prolog. Like "No, I am definitely not a pie!"
To give me the number 7 and next example "w0w such t3xt... to give number 5.
I had thougt about subtract that are a library function and only get back white-characters. But the problem then is No way will give back 5 and not two words.
I thought about
filter([],L).
filter([X,Y|XS],[Y|XS]):- X = ' ',Y = ' ',L = [Y|XS], filter([Y|XS],L).
filter([X|XS],L):- filter(Xs,L).
That will remove white spaces and get back No way but it dosent work anbody have a tip.
Strings in Prolog are lists of character codes not of atoms, what explains why tests like X=' ' fail. See what is the result of executing
write("ab cd"), nl.
in your Prolog system.
You have errors in your 3 clauses:
What to do you expect the first clause to return in the last argument?
L is, as any other variable in a Prolog program, a variable that is local to the clause it appears in, never a global variable.
The second clause unifies L with a list and you use it as second argument of the recursive call: do you expect the recursive call to change the value of L? This will never be the case: in Prolog there is no assignment of variables, changes are made by building terms and unifying them with new variables.
What happens to X in your third clause???

Prolog beginner. How to take list as parameter and pass it on

I am a total beginner at Prolog. I am struggling with creating a rule, which takes a list as parameter and passes the list onto another rule. Here is my code:
combine([], '').
combine([L|List], Total) :-
combine(List, CombinedRest),
atom_concat(L, CombinedRest, Total).
findHeadline([W|Words], Combined) :-
combine(Words, Combined).
findHeadline2([Words], Combined) :-
combine(Words, Combined).
findHeadline works as expected, but findHeadline2 does not. Here is the output:
1 ?- findHeadline([billig, enkeltmand], Combination).
Combination = enkeltmand.
2 ?- findHeadline2([billig, enkeltmand], Combination).
false.
The output I was expecting from findHeadline was:
Combination = billigenkeltmand.
How can it be that this does not work?
I tried to utilize trace in SWI-prolog, but it gave me no clue whatsoever, as the findHeadline rule just exits immediately and does not call the combine rule at all.
It is not very clear what it is exactly that you are after. If you just want to concatenate a list of atoms to get one atom, use atomic_list_concat/2 available in SWI-Prolog:
?- atomic_list_concat([foo, bar, baz], C).
C = foobarbaz.
At the moment, your findHeadline2/2 reads:
"Take a list containing exactly one element, and combine/2 that element."
This is not what you are after, I have the feeling.
Your findHeadline/2, on the other hand, says:
"Take a list of at least one element, and combine/2 all elements except the first".
This is important: never ever ignore compilation warnings. You get code that does something, but you can be almost certain that it does not do what you want it to do, which is bad, or that if someone else reads your code, they will be confused, which is also bad.

Prolog replace element in a list with another list

*Hi, i am trying to replace an element from a list with another list and im stuck when turbo prolog gives me syntax error at the case where if C=A-> put in result list(L1) the list that replace the element.
domains
list=integer*
element=i(integer);l(list)
lista=element*
predicates
repl(list,integer,list,lista)
clauses
repl([],A,B,[]):-!.
repl([C|L],A,B,**[l(|L1])**:- C=A,repl(L,A,B,L1),!.
repl([C|L],A,B,[i(C)|L1]):- repl(L,A,B,L1),!.
Thanks for help, problem solved (using dasblinkenlight code)
Try this:
concat([],L,L).
concat([H|T],L,[H|Res]) :- concat(T,L,Res).
repl([],_,_,[]).
repl([Val|T],Val,Repl,Res) :- repl(T,Val,Repl,Temp), concat(Repl,Temp,Res).
repl([H|T],Val,Repl,[H|Res]) :- repl(T,Val,Repl,Res).
I do not know if it is going to work in Turbo Prolog, but it works fine in SWI, and it does not use any built-in predicates.
concat/3 pair of rules concatenates lists in positions 1 and 2 into a resultant list in position 3.
The first repl deals with the empty list coming in; it is identical to yours, except it replaces singleton variables with underscores (a highly recommended practice)
The second rule deals with the situation where the value Val being replaced is at the head of the list; it replaces the values in the tail, and concatenates the replacement list Repl with the result of the replacement Res.
The last rule deals with the situation when the head value does not match the Val. It recurses down one level, and prepends the head of the initial list to the head of the result of the replacement.
As a side note, the cut operator ! is rarely necessary. In case of this problem, you can definitely do without it.

how to implement if-then-else in prolog

I have tried so many things but I could not found How I can implement following wish in prolog .
if list is empty
call foo function
else
do nothing
What I did:
list = [] -> foo(...)
;
fail.
But, it does not work
fail does not mean "do nothing", but "fail (and backtrack)".
You need to use true instead:
( List == [] -> foo(...) ; true ),
Also, List should be a variable, so use upper case.
Another, perhaps more idiomatic, way to write this would be
% foo_if_empty(?List) call foo if list is empty
foo_if_empty([]) :- !,foo(...).
foo_if_empty(_).
What my code does is to unify with the first clause if list is empty.
If so, we do a cut. If foo fails, we don't want mypred to succeed. So we don't want to do the second clause. The cut eliminates that possiblity.
Now, if we don't unify with the first clause we'll certainly unify with the second. And it does nothing.
This is a much more idiomatic way of doing if/then/else in Prolog than using ->. -> is usually just used for situations where introducing another pred would obscure rather than enlighten the code, similar to the ?: operator in curly brace languages.

Resources