Home > Archive > Prolog > December 2004 > prolog question
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| shoko2004 2004-12-11, 3:58 pm |
| i need to write the following program:
%count_type(Term,Type,Number)
i have written the program but it get stuck in T=..L
when i run the following predicate
count_type(f(g(1,A),A,[1,B,h(C)]),variab
le,Number).
what is the problem with my program.
count_type(T,Y,N):-
Y==numeric,
numeric(T),!,
retract(counter(Y)),
X is Y+1,
asserta(counter(X)).
count_type(T,Y,N):-
Y==atom,
(atomic(T)),!,
retract(counter(Y)),
X is Y+1,
asserta(counter(X)).
count_type(T,Y,N):-
Y==variable,
var(T),!,
retract(counter(Y)),
X is Y+1,
asserta(counter(X)).
count_type([X|Xs],T,N):- !,
count_type(X,T,N),
count_type(Xs,T,N).
count_type(T,Y,N):-
T=..L,
count_type(L,Y,N).
| |
| tmp123 2004-12-11, 3:58 pm |
| shoko2004 wrote:
> i need to write the following program:
> %count_type(Term,Type,Number)
> i have written the program but it get stuck in T=..L
> when i run the following predicate
> count_type(f(g(1,A),A,[1,B,h(C)]),variab
le,Number).
> what is the problem with my program.
>
> count_type(T,Y,N):-
> Y==numeric,
> numeric(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
> count_type(T,Y,N):-
> Y==atom,
> (atomic(T)),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type(T,Y,N):-
> Y==variable,
> var(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type([X|Xs],T,N):- !,
> count_type(X,T,N),
> count_type(Xs,T,N).
>
> count_type(T,Y,N):-
> T=..L,
> count_type(L,Y,N).
Hi,
Nice program, a good example of cut usage.
The major problem I see is that clause T=..L is very generic. That is,
near that anything will match it. By example:
a=..L => L=[a]
[]=..L => L=[[]]
I do not known your objectives, but probably T=..[F|L] helps a few.
In addition, some very small comments, probably just editorial
subjects:
retract(counter(Y????)), Y is not a number.
what is N in your rules?
addition of ! after T=..L ?
something for the empty list: count_type([],.... ?
nicer count_type(T,numeric,N) :- .... than count_type(T,Y,N) :-
Y==numeric, .... ?
Hope useful,
Kind regards.
| |
| Bart Demoen 2004-12-13, 4:07 pm |
| tmp123 wrote:
> shoko2004 wrote:
>
>
>
>
> Hi,
> Nice program, a good example of cut usage.
> The major problem I see is that clause T=..L is very generic. That is,
> near that anything will match it. By example:
>
> a=..L => L=[a]
> []=..L => L=[[]]
>
> I do not known your objectives, but probably T=..[F|L] helps a few.
>
> In addition, some very small comments, probably just editorial
> subjects:
>
> retract(counter(Y????)), Y is not a number.
> what is N in your rules?
> addition of ! after T=..L ?
> something for the empty list: count_type([],.... ?
> nicer count_type(T,numeric,N) :- .... than count_type(T,Y,N) :-
> Y==numeric, .... ?
>
> Hope useful,
> Kind regards.
>
Both the original poster and the replying poster have a problem - but
of a different kind. I will address both. First the OP.
Guessing ... the OP wants to count the number of nodes in a Prolog
term "tree", but only the nodes of a particular "type" (variable,
numeric or otherwise atomic) - as a side remark: when asking for help,
please tell us what your program is supposed to do, or which problem
you are trying to solve, because from a piece of code you yourself
describe as "it get stuck" it is impossible to deduce that.
Allow me to first give a general advice regarding the use of Prolog,
actually three advices:
1) don't use dynamic predicates
2) don't use dynamic predicates
3) don't use dynamic predicates
Here are the 3 most important reasons:
if you use dynamic predicates
1) you make more mistakes
2) you abuse them eventually
3) your programs are worse
I do not know how to help you further, except by following my hunch on
what you are trying to achieve and point out the similarity between
if I am counting numbers and the term contained already 13
numbers, and what I see now is a number, then the term
contains 14 numbers up to now
and
count(Term,What,AlReady,UpToNow) :-
What == number,
number(Term),
!,
UpToNow is AlReady + 1.
There are ways to write this (in the context of the whole program)
without a cut (!), but that's for the next lesson if you care.
BTW, number/1 is an ISO Prolog builtin - numeric/1 is not.
Now the reply the OP got from tmp123 - as a side remark: beginner's
questions are ok; they remind us how we also struggled with basic
stuff, and they allow us to show the right path to LP.
But replies as from tmp123 ... please no more !
My advice to tmp123: ask advice, do not offer it.
tmp123 writes:
> Nice program, a good example of cut usage.
How can one judge the niceness of a program without knowing what it is
supposed to solve ?
"a good example of cut usage" please, give us a break ...
> The major problem I see is that clause T=..L is very generic. That is,
> near that anything will match it. By example:
>
> a=..L => L=[a]
> []=..L => L=[[]]
>
> I do not known your objectives, but probably T=..[F|L] helps a few.
The only part that makes sense in these sentences is
I do not known your objectives
all the rest is gibberish, dangerous noise, because it gives the
impression of knowing the subject matter - believe me, tmp123 doesn't.
> In addition, some very small comments, probably just editorial
> subjects:
and what follows is indeed a comment focussing on "editorial" issues,
not related to understanding; it is commenting on form, not
contents. We can only hope that tmp123 meant it as a sick joke ...
In any case, I beg the OP: ignore the response from tmp123, except for
the part
> Kind regards.
The OP can get better help/response/advice from comp.lang.prolog than
from tmp123 (but make more clear what you want to do).
Cheers
Bart Demoen
ps. yes, I am back :-)
| |
| tmp123 2004-12-14, 9:07 am |
| Bart Demoen wrote:
> ps. yes, I am back :-)
Hi Bart,
Nice to read you again.
Your answer is, in my opinion, a few too much.
I think google is not a good place for long non-technical discussions,
so this is my last post to this or any other reply you make to this
subject. I will open a new thread in this post continuing with the
techinical subject. (assumption: if the original author still
interested, then it is not a homework: I can be more exact on my
comments). I think your technical opinion will be an important
contribution. One example, about how to skip cut and its variants.
| |
| Torkel Franzen 2004-12-14, 9:07 am |
| "tmp123" <tmp123@menta.net> writes:
> I think google is not a good place for long non-technical
> discussions,
I'm sure the people at Google have long non-technical discussions,
but we can't participate. News is however an excellent place for
long non-technical discussions between people from different parts
of the world.
| |
| tmp123 2004-12-14, 9:07 am |
| One example of the application of the previous comments to the rule for
"numbers". It is assumed this rule means "if T is a number, and we are
counting numbers, then number of numbers, N, is 1". With this
definition of N, it is not necessary to use retract/assert.
count_type(T,Y,1):-
Y==numeric,
numeric(T), !.
"numeric" can be changed by standard "number".
Now, the other case for numbers: "if T is a number, but we are looking
for something else, then N is 0". In this way, it is sure that no
numbers will progress to next rules. Using parameter matching instead
of == we will have the following rules:
count_type(T,numeric,1) :- number(T), !.
count_type(T,_Y,0) :- number(T), !.
Same for atoms and variables.
Going for a few more complex rule: the list.
First one "the number of anything in a empty list is 0".
count_type([],_Y,0) :- !.
Next one, the number of something in a list is the number of something
in the head more its number in the rest:
count_type([H|Q],Y,Z) :- !,
count_type(H,Y,Z1),
count_type(Q,Y,Z2),
Z is Z1+Z2.
Finally, the case of terms. At this point, atom, numbers, list, ...
have already analized, so I can suposse only rest terms with functor
and arity >=0. The rules is: the number of anything in a term is the
number of anything in the functor (?) plus the number in the
"parameters".
count_type(T,Y,Z) :-
T=..[F|Q], !,
count_type(F,Y,Z1),
count_type(Q,Y,Z2),
Z is Z1+Z2.
Finally, a completion, for not covered cases:
count_type(_,_,0).
Hope nothing forgot. Time for TECHNICAL comments and improvements (I'm
sure experts can improve it a lot). Some posibilities:
- Make rules tail recursive using 4 parameters.
- Skip cut and -> and similars.
- ...
| |
| Matthew Huntbach 2004-12-14, 9:07 am |
|
On Sat, 11 Dec 2004, shoko2004 wrote:
> i need to write the following program:
> %count_type(Term,Type,Number)
> i have written the program but it get stuck in T=..L
> when i run the following predicate
> count_type(f(g(1,A),A,[1,B,h(C)]),variab
le,Number).
> what is the problem with my program.
>
> count_type(T,Y,N):-
> Y==numeric,
> numeric(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
> count_type(T,Y,N):-
> Y==atom,
> (atomic(T)),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type(T,Y,N):-
> Y==variable,
> var(T),!,
> retract(counter(Y)),
> X is Y+1,
> asserta(counter(X)).
>
>
> count_type([X|Xs],T,N):- !,
> count_type(X,T,N),
> count_type(Xs,T,N).
>
> count_type(T,Y,N):-
> T=..L,
> count_type(L,Y,N).
>
In the first three clauses you seem to be trying to use the variable
Y for two different things, one as a string to indicate the type
you're counting, the other as an integer to hold a count. But the
variable N doesn't get used at all.
As Bart suggests, a good rule is don't use dynamic predicates.
It's often the case that the use of such predicates indicates
a failure to think declaratively. In this case you are using one
just to keep a rewriteable count, but why not just:
count_type([X|Xs],T,N):- !,
count_type(X,T,N1),
count_type(Xs,T,N2),
N is N1+N2.
?
Even when programming in an imperative language, this would be the obvious
way to do it leading to cleaner code, rather than having a global variable
which is updated.
The time when a dynamic predicate to give an updateable count *is*
required in Prolog is when you are keeping a count which is updated over
backtracking. Prolog novices often waste many hours because no-one told
them you can't maintain information over backtracking except through
the use of assert.
Matthew Huntbach
|
|
|
|
|