Code Comments

Programming Forum and web based access to our favorite programming groups.
For Programmers: Free Programming Magazines | New: Database administration forum
Registration is free! Edit your profileCalendarFind other membersFrequently Asked QuestionsSearch -> 
Post New Thread











Thread
Author

Any way to tail-recurse this?
Just adding up numbers in a list.  I already know you could do the
below better, cleaner, and in fewer steps.  My question is how to tail-
recurse it, if possible.

(the first arg in the predicate is the list, the second is the
"total")

Thanks.
---------------------

addlist([],0).
addlist([X],X).
addlist([H|[X]],Y) :- Y is H+X.  %This pred is probably unnecessary,
but aids my understanding
addlist([H1|[H2|T]],Y1) :- addlist([H2|T],Y2), Y1 is H1+Y2.


Report this thread to moderator Post Follow-up to this message
Old Post
pineapple.link@yahoo.com
08-22-07 03:07 AM


Re: Any way to tail-recurse this?
Think I figured out one....

addlist([],0).
addlist([X],X).
addlist([First|[Second|Rest]],Total) :- Total2 is Total-First,
addlist([Second|Rest], Total2).


Report this thread to moderator Post Follow-up to this message
Old Post
pineapple.link@yahoo.com
08-22-07 01:06 PM


Re: Any way to tail-recurse this?
On Wed, 22 Aug 2007 14:33:56 +0200, <pineapple.link@yahoo.com> wrote:

> Think I figured out one....
>
> addlist([],0).
> addlist([X],X).
> addlist([First|[Second|Rest]],Total) :-        Total2 is Total-First,
>         addlist([Second|Rest], Total2).

Ingenious, but addlist([1,2,3],T) to calculate the sum does not work.
It can only check that the sum you supply is correct.
I think you have not found the solution of the exercise yet.  :)

Note that [A|[B|C]] is the same as [A,B|C].
The second way of writing is easier to read.

P.

Report this thread to moderator Post Follow-up to this message
Old Post
Pierpaolo BERNARDI
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
In article <op.txgr0vo1xbm8ci@eraora>,
"Pierpaolo BERNARDI" <pierpaolo@secondbox.net> wrote:

> On Wed, 22 Aug 2007 14:33:56 +0200, <pineapple.link@yahoo.com> wrote:
> 
>
> Ingenious, but addlist([1,2,3],T) to calculate the sum does not work.
> It can only check that the sum you supply is correct.
> I think you have not found the solution of the exercise yet.  :)
>
> Note that [A|[B|C]] is the same as [A,B|C].
> The second way of writing is easier to read.
>
> P.

addlist([],0).
addlist([X],X).
addlist([First, Second|Rest],  Total) :-
Sum is First+Second,
addlist([Sum|Rest],  Total).

Report this thread to moderator Post Follow-up to this message
Old Post
Steve Harlow
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
>  "Pierpaolo BERNARDI" <pierpaolo@secondbox.net> wrote: 

Thanks (my own personal exercise, BTW - not a class I'm taking).

What, exactly, is the "rule" for activating the ability to have Prolog
"fill in" a variable... in this case calculating the sum?  Is it
something to do with "instantiation" or "non-instantiation" of a
variable?
 
> addlist([],0).
> addlist([X],X).
> addlist([First, Second|Rest],  Total) :-
>          Sum is First+Second,
>          addlist([Sum|Rest],  Total).

Excellent!  Much easier to understand.  Now why didn't I think of that?


Report this thread to moderator Post Follow-up to this message
Old Post
pineapple.link@yahoo.com
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
On Wed, 22 Aug 2007 16:31:46 +0100, Steve Harlow wrote:


> addlist([],0).
> addlist([X],X).
> addlist([First, Second|Rest],  Total) :-
>          Sum is First+Second,
>          addlist([Sum|Rest],  Total).

You are now just a small step away from a tailrecursive version,
that keeps the head of the list as a separate accumulating parameter:

addlist([],0).
addlist([X|R],N) :- addlist(R,X,N).

addlist([],N,N).
addlist([X|R],In,Out) :- NewIn is In + X, addlist(R,NewIn,Out).

The usual tailrecursive version of addlist goes like this however:

addlist(L,N) :- addlist(L,0,N).

<and then the addlist/3 definition above>

It is worthwhile trying to give a declarative reading of addlist/3.


Tailrecursive predicates are usually associated with an accumulating
parameter. There is also a direct relation with a while loop for
computing the sum of the list elements in an imperative language:

result := 0;  % initialize the accumulating parameter
while not at end of list
result := result + head(list);
list := tail(list)

Cheers

Bart Demoen

Report this thread to moderator Post Follow-up to this message
Old Post
bart demoen
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
> You are now just a small step away from a tailrecursive version,
> that keeps the head of the list as a separate accumulating parameter:

I am impressed with your analysis, and code contribution.  However,
are you saying that the above code (the poster above you, and perhaps
my last attempt as well, albeit an uglier version) is NOT tail-
recursive?  From what I have read, it seems that it should be.  It
does some work and gets that stuff "out of the way," and then lastly
calls itself again.

If it is not tail-recursive, can you tell me why not?

Thanks.


Report this thread to moderator Post Follow-up to this message
Old Post
pineapple.link@yahoo.com
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
On Wed, 22 Aug 2007 10:15:45 -0700, pineapple.link wrote:
 
>
> I am impressed with your analysis, and code contribution.  However,
> are you saying that the above code (the poster above you, and perhaps
> my last attempt as well, albeit an uglier version) is NOT tail-
> recursive?  From what I have read, it seems that it should be.  It
> does some work and gets that stuff "out of the way," and then lastly
> calls itself again.
>
> If it is not tail-recursive, can you tell me why not?

Your version was tail-recursive.

I should have been more clear and written something like:

You are a small step away from a tailrecursive version that at
the same time keeps ... as a separate accu.

It is kind of a waste to put the accu in a datastructure - but as the
other poster noted, quite cunning.

Now that I am at it, maybe a little thing on case analysis.
if you deal with lists, there are usually only two cases: the empty list
and the non-empty list. If you think a predicate that deals with lists
needs more than these two cases, there are only the following five
possibilities:

you are wrong and need to rethink
you are wrong and need to rethink
you are wrong and need to rethink
you are wrong and need to rethink
you were right

:-)

Cheers

Bart Demoen

Report this thread to moderator Post Follow-up to this message
Old Post
bart demoen
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
Thanks - I hope I'm learning a little something here.  Tell me - why
is it a waste to keep the accumulator in the data structure (albeit
cunning, as you mentioned), and what is the advantage of the way you
do it?

Again, thanks.

(It is quite difficult to get the "hang" of this "thinking
recursively," but I'm trying, and at least I did come up with a
recursive solution, albeit an ugly one, heh)


Report this thread to moderator Post Follow-up to this message
Old Post
pineapple.link@yahoo.com
08-23-07 12:07 AM


Re: Any way to tail-recurse this?
On Wed, 22 Aug 2007 11:18:39 -0700, pineapple.link wrote:

> Thanks - I hope I'm learning a little something here.  Tell me - why
> is it a waste to keep the accumulator in the data structure (albeit
> cunning, as you mentioned), and what is the advantage of the way you
> do it?
>
> Again, thanks.
>
> (It is quite difficult to get the "hang" of this "thinking
> recursively," but I'm trying, and at least I did come up with a
> recursive solution, albeit an ugly one, heh)

It wasn't ugly. But it is a bit more difficult to understand.
Because ...
When one tries to give a declarative reading of a predicate, one
usually tries to establish a relationship between the arguments
of the predicate. For instance for my

addlist([],N,N).
addlist([X|R],In,Out) :- NewIn is In + X, addlist(R,NewIn,Out).

the relationship addlist/3 establishes between its three arguments
X,Y and Z is

Z equals the sum of Y and the value of every element in X

That is made a bit easier by having the extra accumulator argument.

When you hide the accumulator inside another argument of a predicate,
a similar statement usually becomes more involved. Since you wrote your
version of addlist yourself, maybe you should try to come up with a
reading that gives a relationship between its arguments.

About the waste - let me first repeat your definition of addlist/2

addlist([],0).
addlist([X],X).
addlist([First, Second|Rest],  Total) :-
Sum is First+Second,
addlist([Sum|Rest],  Total).

It is clear to us that the recursive call only can match the heads of the
second and third clause of addlist/2 - most Prolog systems don't exploit
this - XSB is an exception. For most implementations, it is a waste of
cpu cycles to construct a list with first element Sum, just to take the
list apart in the next activation of addlist - a waste in time and space.
But you might not be interested in efficiency of course.
The waste is then solely in the brain cycles to understand it, because
the reading is more difficult (I'm challenging you for the second time :-)

Cheers

Bart Demoen

Report this thread to moderator Post Follow-up to this message
Old Post
bart demoen
08-23-07 12:07 AM


Sponsored Links




Last Thread Next Thread Next
Search this forum -> 
Post New Thread

Prolog archive

Show a Printable Version Send to friend Email This Page to Someone! subscribe to this thread Receive updates to this thread
Computer Consultants
Programming Jobs
Visual Basic Controls
SQL Server Programming
Webservices
Java Security
Visual Studio
C# Programming
Visual J++
Software engineering
Open source Software
Perl Programming
PHP Programming
ASP Programming
ASP .NET Programming
Visual Basic Programming
Windows Scripting Host
Java Programming
Java Help
Java Beans
VBScript
Cobol
MAC Applications
Unix Programming
Forum Jump:
All times are GMT. The time now is 05:01 PM.

 
Free MCSE Braindumps | Real Estate Topics

Programming forum archive

Copyrights CodeComments.com 2004 - 2006

Powered by vBulletin Copyright 2000-2006 Jelsoft Enterprises Limited.