Thread View: net.applic
1 messages
1 total messages
Started by S.R.L.Meira
Tue, 16 Aug 1983 09:50
recursion and efficiency and krc
Author: S.R.L.Meira
Date: Tue, 16 Aug 1983 09:50
Date: Tue, 16 Aug 1983 09:50
112 lines
3547 bytes
3547 bytes
This article is about recursion (and factorial!) again, in relation
to Joe Fasel's. The examples are in KRC --The Kent Recursive
Calculator-- parts of which have been shown in a previous article
(RECURSION IS EASIER...).
The "usual" definition of factorial
fac1 0 = 1
fac1 n = n * fac1 (n-1)
is not only the simplest way to demonstrate recursion, but it is prob-
ably the most efficient way for the calculation of factorial (in a
purely applicative language). The second method shown in Joe's article
uses the "lazy list" concept, i.e., using the notation
lis n = [1..n]
one defines the list
[1,2,3...n]
which is built by need. The in(de)crement is not necessarily 1, such
that
odd = [1,3..]
is the infinite list of odd integers. And so on. But when we define
factorial as
fac2 n = product [1..n]
its evaluation uses much more space than fac1's above. In the
ICL2960/EMAS (tree-rewriting-system) implementation of KRC (by D.
Turner) fac2 uses 60% more space than fac1 and in the experimental Unix
(combinators) implementation (by S. Croft) it uses 200% more space, the
number of reductions needed for both evaluations being basically
unchanged.
I agree with Joe (and David Turner) that the use of product, a KRC
library function defined by
product = fold '*' 1
fold op s [] = s
fold op s (a:x) = op a (fold op s x)
eliminates the "junk recursion" in fac1, but it has its price.
By the way, the use of tail recursion
fac3 n = fac3t n 1
fac3t 0 r = r
fac3t n r = fac3t (n-1) (n*r)
is also less efficient in the two implementations of KRC here at UKC.
fac3 evaluates with the same number of reductions of fac1, but it uses
20% more space in the tree-rew-sys and 50% more in the combinatoric
machine. So...
Now I'll say a little about eliminating recursion by using ZF-
expressions (see my previous article). A silly example of its use is to
redefine the length function
length [] = 0
length (a:x) = 1 + length x
whose ZF version is
lenZF x = sum {1 | a <- x}
where {1 | a <- x} is a list containing as many 1's as the number of
elements in x, and sum is
sum = fold '+' 0
A favourite example is the infinite list of primes
primes = sieve [2..]
sieve (a:x) = a : sieve {b | b <- x; b % a = 0}
where % is "remainder" and \= is "not equal".
From now on, we can redefine
map f [] = []
map f (a:x) = f a : map f x
as
map f x = {f a | a <-x}
and
filter cond [] = []
filter cond (a:x) = a : filter cond x, cond x
= filter cond x
as
filter cond x = {a | a <- x; cond a}
and so on.
The only alert here is that both "product" and ZF-expressions are
(internally) recursively defined.
Silvio Lemos Meira
...!decvax!mcvax!ukc!srlm
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads