Article View: comp.lang.logo
Article #246Re: um, maybe this is a silly question
From: Brian Harvey
Date: Sun, 11 Oct 1992 21:57
Date: Sun, 11 Oct 1992 21:57
103 lines
5591 bytes
5591 bytes
ergo@netcom.com (Isaac Rabinovitch) writes:
>This raises two questions: First, Why does your book (*Computer Science
>Logo Style*) spend so much time on make and on "instruction sequence"
>programs?
Well, Logo is sort of a compromise in this regard. Functional programming
is great for computing the values of functions, as in the GCD example.
For something like turtle graphics, or an interactive question-and-answer
program, sequential programming seems more natural.
CSLS emphasizes sequential programming more heavily than I might have liked
because it's pretty hard to write interesting functional programs until you
have either recursion or higher-order functions like MAP. That's why the
examples in the early chapters are more sequential. These days, when I
teach a Logo class using my book as a text, I generally introduce the
higher-order functions as black boxes right from the beginning, and that
lets me show interesting functional examples earlier. (Of course, this
approach makes students confront the function-as-data issue sooner.) I'm
thinking about a second edition, based on Berkeley Logo, and if I do that
it'll take advantage of the fact that MAP and FILTER and so on are provided
as primitives.
[Also, to be entirely honest, I wrote volume 1 before I'd read Abelson and
Sussman, so I only partly understood the True Religion.]
> Second, how do you justify the abolition of assignment and
>iteration to someone who is used to using them? I don't mean the
>fancy doctrines about denotational elegance and all that. Few
>programmers are interested in that stuff, assuming they can understand
>it. What are the *practical* advantages?
Well, it's hard to answer a question if you rule out the answer in advance.
I don't see such a sharp line between "practical advantages" and "fancy
doctrines" as you do. Certainly there is *no* advantage to functional
programming from the point of view of machine efficiency. The difference
is entirely in the mind of the programmer, and so it's hard to justify
without making reference to the functional metaphor ("doctrine"). Logo
isn't purely functional and doesn't make an all-or-nothing principle of
this, but it's clear to me that some hard problems become easy problems
if you think about them in terms of recursive functions.
One of my standard anecdotes about this comes from a data structures class
that I taught a few years ago, in C, to students who had taken the Abelson
and Sussman (Scheme) course. They were given the following midterm problem:
Write a function that takes three arguments: a binary search tree
and two numbers (called low and high). The function should return
a sequential linked list containing those numbers from the tree
that are in the range low < x < high. Your program should not
examine any tree nodes if it can be deduced from already-seen nodes
that they can't be part of the result.
What we were looking for was the C equivalent of this Logo function:
to range :tree :low :high
if empty.tree? :tree [op []]
if (root.node :tree) < :low [op range (right.branch :tree) :low :high]
if (root.node :tree) > :high [op range (left.branch :tree) :low :high]
op (se range (left.branch :tree) :low :high
root.node :tree
range (right.branch :tree) :low :high)
end
Hardly anyone got this question right, because they all tried to solve it
iteratively. Even the ones who used recursion ignored the return value in
the recursive call, and tried to use global variables to keep track of
their position in the tree. So in class the next day I said "okay, write
this in Scheme" and many of them were able to do that. Why not in C? Because
they had the attitude that Real Men don't use recursive functions in C
programs.
>Incidentally, you probably should make it clear that you're talking
>about a specific kind of recursion, namely tail recursion. Most C
>programmers will look at your Euclid's example, scratch their heads,
>and say, "Gee, that's OK if you can set aside a meg for the stack.
>These list guys sure don't know how to program in the real world...."
No, I'm not especially interested in tail recursion. If a problem
(such as the GCD one) happens to be naturally iterative, so that its
recursive solution happens to be tail recursive, then we get runtime
efficiency as an added bonus. But as a teacher I couldn't care less
about efficiency. If I am teaching students about the factorial function
I would much rather have them write the natural, understandable
to fact :n
if :n=0 [output 1]
output :n * fact (:n-1)
end
than the tail recursive but incomprehensible
to fact :n
output fact.helper :n 1
end
to fact.helper :n :result
if :n=0 [output :result]
output fact.helper :n-1 :result*:n
end
By the way, Euclid's algorithm converges quite quickly for most inputs, so
even an implementation that doesn't support tail recursion elimination is
hardly likely to require a meg of stack!
Technical Details
Message-ID:
<1ba7vcINNpam@agate.berkeley.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!ukma!usenet.ins.cwru.edu!agate!anarres.CS.Berkeley.EDU!bhReferences:
<1992Oct9.123626.15852@cbfsb.cb.att.com> <1b44g5INNqq1@agate.berkeley.edu> <1992Oct11.192128.5448@netcom.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!ukma!usenet.ins.cwru.edu!agate!anarres.CS.Berkeley.EDU!bh From: bh@anarres.CS.Berkeley.EDU (Brian Harvey) Newsgroups: comp.lang.logo Subject: Re: um, maybe this is a silly question Date: 11 Oct 1992 21:57:00 GMT Organization: University of California, Berkeley Lines: 103 Distribution: usa Message-ID: <1ba7vcINNpam@agate.berkeley.edu> References: <1992Oct9.123626.15852@cbfsb.cb.att.com> <1b44g5INNqq1@agate.berkeley.edu> <1992Oct11.192128.5448@netcom.com> NNTP-Posting-Host: anarres.cs.berkeley.edu