From: JB
Subject: The value of a loop
Date: 
Message-ID: <3d993098_5@news.newsgroups.com>
How can I return a value from a loop construct? The 
following example looks a bit ugly (though it works).
The let is probably superflous too.

(defun nthroot (n a)
  (let ((x 1.0L0) (x0 0.0L0))
     (loop 
       while (/= x x0) ;iterate until there is no change
       do (setq x0 x
         x  (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)))
     x))
-- 
Janos Blazi


-----------== Posted via Newsfeed.Com - Uncensored Usenet News ==----------
   http://www.newsfeed.com       The #1 Newsgroup Service in the World!
-----= Over 100,000 Newsgroups - Unlimited Fast Downloads - 19 Servers =-----

From: Vassil Nikolov
Subject: Re: The value of a loop
Date: 
Message-ID: <kzbheg6ya2d.fsf@panix2.panix.com>
JB <··@yahoo.de> writes:

> How can I return a value from a loop construct? The 

LOOP has a RETURN clause.  See
http://www.lispworks.com/reference/HyperSpec/Body/06_agb.htm.

It is also possible to have (RETURN expression) in the body of a loop,
though as a matter of style I wouldn't mix that with clauses.

I would also refrain from doing a (RETURN-FROM NTHROOT X) here, again
as a matter of style, since there is no nesting of blocks in this
case.

> following example looks a bit ugly (though it works).
> The let is probably superflous too.

Yes, you can have the loop declare its variables---see
http://www.lispworks.com/reference/HyperSpec/Body/06_abb.htm.

> (defun nthroot (n a)
>   (let ((x 1.0L0) (x0 0.0L0))
>      (loop 
>        while (/= x x0) ;iterate until there is no change
>        do (setq x0 x
>          x  (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)))
>      x))

By the way, the loop should terminate when X and X0 are sufficiently
close to one another, not when they are exactly equal.  Also, the
returned value should really be of the same type as A, since if A is
(say) a single-float, returning a long-float makes little sense.
(See COERCE.)

(These are all remarks about what is immediately visible---I did not
check if the algorithm is implemented correctly.)

---Vassil.
From: Vassil Nikolov
Subject: Re: The value of a loop
Date: 
Message-ID: <kzbbs6ey9o3.fsf@panix2.panix.com>
Vassil Nikolov <··········@poboxes.com> writes, not quite correctly:

> LOOP has a RETURN clause.  See
> http://www.lispworks.com/reference/HyperSpec/Body/06_agb.htm.

The above should read: LOOP has a FINALLY clause etc.

> It is also possible to have (RETURN expression) in the body of a loop,
> though as a matter of style I wouldn't mix that with clauses.
> 
> I would also refrain from doing a (RETURN-FROM NTHROOT X) here, again
> as a matter of style, since there is no nesting of blocks in this
> case.

The above is not really relevant to the question asked.

Should re-read before posting, not after...

---Vassil.
From: JB
Subject: Re: The value of a loop
Date: 
Message-ID: <3d993ede_8@news.newsgroups.com>
Vassil Nikolov wrote:
> By the way, the loop should terminate when X and X0 are > 
> sufficiently close to one another, not when they are
> exactly equal.

The reason of this program was to show my pupils, how things 
worked in different programming languages. We had the idea 
that we try to imitate or calculators and iterate until 
there is no visible change. We did not know in advance, 
what "sufficiently close" means.

> Also, the returned value should really be of the same type
> as A, since if A is (say) a single-float, returning a
> long-float makes little sense. (See COERCE.)

Thx. I must admit that I do not understand how this works. I 
prefer entering
(nthroot 5 7)
and getting 
1.47577316159455206927691669563224410654409361374020356777090416888455L0

Now if I omit the "L0" in 1.0L0 and 0.0L, this does not 
work, so I set them and then it works (with clisp at 
least). When I omit the "L0", then entering
(nthroot 5 7.0L0)
does not help either. (Then I am wirking with floating point 
numbers of different precision and clisp does not like 
that.)

-- 
J.... B....


-----------== Posted via Newsfeed.Com - Uncensored Usenet News ==----------
   http://www.newsfeed.com       The #1 Newsgroup Service in the World!
-----= Over 100,000 Newsgroups - Unlimited Fast Downloads - 19 Servers =-----
From: Vassil Nikolov
Subject: Re: The value of a loop
Date: 
Message-ID: <kzbelba8vhl.fsf@panix3.panix.com>
JB <··@yahoo.de> writes:

> Vassil Nikolov wrote:
> > By the way, the loop should terminate when X and X0 are > 
> > sufficiently close to one another, not when they are
> > exactly equal.
> 
> The reason of this program was to show my pupils, how things 
> worked in different programming languages. We had the idea 
> that we try to imitate or calculators and iterate until 
> there is no visible change. We did not know in advance, 
> what "sufficiently close" means.

But you know the precision of the calculator, and that should give you
an idea of `sufficiently close.'

Besides, I am not sure numerical computations such as this one always
terminate if the test is for strict equality.


> > Also, the returned value should really be of the same type
> > as A, since if A is (say) a single-float, returning a
> > long-float makes little sense. (See COERCE.)
> 
> Thx. I must admit that I do not understand how this works. I 
> prefer entering
> (nthroot 5 7)
> and getting 
> 1.47577316159455206927691669563224410654409361374020356777090416888455L0
> 
> Now if I omit the "L0" in 1.0L0 and 0.0L, this does not 
> work, so I set them and then it works (with clisp at 
> least). When I omit the "L0", then entering
> (nthroot 5 7.0L0)
> does not help either. (Then I am wirking with floating point 
> numbers of different precision and clisp does not like 
> that.)

What I was thinking about was returning

  (if (floatp a) (coerce x (type-of a)) x)

which in fact should be written with a call to FLOAT, not to COERCE,
as

  (if (floatp a) (float x a) x)

as we assume that an integer A is accurate to the maximum degree (of
course, if NTHROOT is rewritten with declarations, those may also be
rewritten, but my concern here is just with matching the precision of
the result with the precision of the argument).

---Vassil.
From: Coby Beck
Subject: Re: The value of a loop
Date: 
Message-ID: <anbcst$51t$1@otis.netspace.net.au>
"JB" <··@yahoo.de> wrote in message ···············@news.newsgroups.com...
> How can I return a value from a loop construct?

Use finally (return <value>)


> following example looks a bit ugly (though it works).
> The let is probably superflous too.
>
> (defun nthroot (n a)
>   (let ((x 1.0L0) (x0 0.0L0))
>      (loop
>        while (/= x x0) ;iterate until there is no change
>        do (setq x0 x
>          x  (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)))
>      x))

(defun nthroot (n a)
  (loop with x = 1.0L0
        with x-old = 0.0L0
        until (= x x-old) do
        (setf x-old x
              x (/ (+ (* (1- n) x)
                      (/ a (expt x (1- n))))
                   n))
        finally (return x)))


--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: JB
Subject: Re: The value of a loop
Date: 
Message-ID: <3d9942c9_2@news.newsgroups.com>
Coby Beck wrote:

Thx. I was a bit surprised that you put the "do" into the 
same line as the until-clause, as "do" starts a new clause, 
doesn't it?

(I like "loop" as it is a bit like me: "geschwaetzig", which 
is the German word for somebody who talks too much.)

-- 
Janos Blazi


-----------== Posted via Newsfeed.Com - Uncensored Usenet News ==----------
   http://www.newsfeed.com       The #1 Newsgroup Service in the World!
-----= Over 100,000 Newsgroups - Unlimited Fast Downloads - 19 Servers =-----
From: Thomas A. Russ
Subject: Re: The value of a loop
Date: 
Message-ID: <ymiadltdisx.fsf@sevak.isi.edu>
JB <··@yahoo.de> writes:

> 
> How can I return a value from a loop construct?

By using RETURN.  It can either be done as a Loop keyword or
via the (RETURN ...) statement.  Loop introduces a NIL block.

> The following example looks a bit ugly (though it works).
> The let is probably superflous too.
> 
> (defun nthroot (n a)
>   (let ((x 1.0L0) (x0 0.0L0))
>      (loop 
>        while (/= x x0) ;iterate until there is no change
>        do (setq x0 x
>          x  (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)))
>      x))

Although not strictly necessary, I use AND to make the assignments in
parallel.  This would work even if the order of the two iteration
clauses were reversed.

(defun nthroot2 (n a)
   (loop for x0 = 0.0L0 then x
         and x  = 1.0L0 then (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)
         when (= x x0) return x))

(defun nthroot3 (n a)
   (loop for x0 = 0.0L0 then x
         and x  = 1.0L0 then (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)
	while (/= x x0)
	finally (return x)))



Although not directly relevant to the question, I would also think you
would want the (in)equality test to use some epsilon value rather than
be strict -- it can make the running time rather long :)

Testing it on ACL with 3.0 26.0 doesn't converge for me.  I get the
following values loop:

*  X  = 2.9624960684073707d0
   X0 = 2.9624960684073702d0

*  X  = 2.9624960684073702d0
   X0 = 2.9624960684073707d0

(defun nthroot4 (n a)
   (loop for x0 = 0.0L0 then x
         and x  = 1.0L0 then (/ (+ (* (- n 1) x) (/ a (expt x (- n 1)))) n)
       while (> (abs (- x x0)) #.(* 2.0L0 LONG-FLOAT-EPSILON))
       finally (return x)))




-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu