From: David Steuber
Subject: I see beauty!
Date: 
Message-ID: <87u1atijyb.fsf@verizon.net>
My first FORTRAN course for its first assignment posed the problem of
writing a program to produce the Fibonacci sequence.  Interestingly
enough, that was also one of the first problems in a Pascal class I
took.  Neither of those languages (or C) let me write something as
brief as this:

(do ((a 1 b) (b 1 (+ a b))) ((> b 10000) a) (print a))

I'll admit it took me a few minutes to fully grok the DO syntax.  And
I thought C's for was pretty cool.

Now to try this thing with (> b 10000) replaced with nil. <eg>

I guess in Perl it would look something like this (using proper
indentation):

for ($a=1,$b=1;$b<10000;$a=$b,$b+=$a) {
  print "$a\n";
}
print "$a\n";

There is a problem though.  The Perl program gives the wrong results.
By the time we get around to incrementing $b, $a has already been
given a new value.  This did not happen in the Lisp expression above.
DO was clever enough to use the *old* value of a.  Or is that so
clever?

In Perl or C, I would need an explicit temporary variable to preserve
the old value of a so that I can use that to increment b.  Lisp
somehow did this behind my back.  I didn't even notice this until
trying the same function in Perl.

So what happened?  Does CMUCL have a bug?  Is there an exception to
left to right evaluation?  Was DWIM(X) invoked?

-- 
One Editor to rule them all.  One Editor to find them,
One Editor to bring them all and in the darkness bind them.

(do ((a 1 b) (b 1 (+ a b))) (nil a) (print a))

From: Kenny Tilton
Subject: Re: I see beauty!
Date: 
Message-ID: <3EEA6C79.4010106@nyc.rr.com>
David Steuber wrote:
> My first FORTRAN course for its first assignment posed the problem of
> writing a program to produce the Fibonacci sequence.  Interestingly
> enough, that was also one of the first problems in a Pascal class I
> took.  Neither of those languages (or C) let me write something as
> brief as this:
> 
> (do ((a 1 b) (b 1 (+ a b))) ((> b 10000) a) (print a))
> 
> I'll admit it took me a few minutes to fully grok the DO syntax.  And
> I thought C's for was pretty cool.
> 
> Now to try this thing with (> b 10000) replaced with nil. <eg>
> 
> I guess in Perl it would look something like this (using proper
> indentation):
> 
> for ($a=1,$b=1;$b<10000;$a=$b,$b+=$a) {
>   print "$a\n";
> }
> print "$a\n";
> 
> There is a problem though.  The Perl program gives the wrong results.
> By the time we get around to incrementing $b, $a has already been
> given a new value.  This did not happen in the Lisp expression above.
> DO was clever enough to use the *old* value of a.  Or is that so
> clever?

yes it is, if that is what you need. if you need the behavior you got in 
Perl, you use DO*. btw, the same goes for LET vs LET*.

> 
> In Perl or C, I would need an explicit temporary variable to preserve
> the old value of a so that I can use that to increment b.  Lisp
> somehow did this behind my back.  I didn't even notice this until
> trying the same function in Perl.
> 
> So what happened?  Does CMUCL have a bug?  Is there an exception to
> left to right evaluation?  Was DWIM(X) invoked?

Just more beauty. Or I should say, more mud. ie, CL tends to make it 
easy to GWYM, by offering lotsa options.

When you are ready, you might drop us some feedback:

    http://www.cliki.net/The%20Road%20to%20Lisp%20Survey



-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Everything is a cell." -- Alan Kay
From: David Steuber
Subject: Re: I see beauty!
Date: 
Message-ID: <87isr7j4ij.fsf@verizon.net>
Kenny Tilton <·······@nyc.rr.com> writes:

> David Steuber wrote:
> > DO was clever enough to use the *old* value of a.  Or is that so
> > clever?
> 
> yes it is, if that is what you need. if you need the behavior you got
> in Perl, you use DO*. btw, the same goes for LET vs LET*.

I was not aware of the existence of the * suffix versions.  Neato.
Knowing this stuff is out there is good for my soul because I hate
magic.  The idea of the compiler going, "I know just what you mean."
scares me.  Then again, when the compiler says that I am missing a ;
at the end of line n, I am always pissed that it just doesn't stick it
in.  It is almost always right in that respect.  At least, I've never
seen it wrong.

> Just more beauty. Or I should say, more mud. ie, CL tends to make it
> easy to GWYM, by offering lotsa options.
> 
> When you are ready, you might drop us some feedback:
> 
>     http://www.cliki.net/The%20Road%20to%20Lisp%20Survey

I'll take a look at that.  Can you define ready?  I assume you mean
that I can do more than work out a trivial little function without
looking at the format for DO every two nanoseconds.

Oh! One other thing.  I really love the transition to bignums!  It
does not take CMUCL long to overflow even a long long (64bit int on my
arch) with this function.  A blink of the eye and you missed it.
There is a lot of work going on in that sequence generator.  Not only
are large numbers computed, they are converted from an internal binary
representation into strings by the print function.  To produce the
exact same effect as the Lisp code in C would be a fair bit of extra
programming, even with a bignum library on hand.  Even in Perl, I
would need the PDL module to do this right.

BTW, the CMUCL garbage collector worked fairly well for this
sequence.  Memory use was rock stable and GC activity was invisible
until after I had let the sucker run for about 18 hours.  Hey, the
CPUs needed warming up ;-)

-- 
One Editor to rule them all.  One Editor to find them,
One Editor to bring them all and in the darkness bind them.

(do ((a 1 b) (b 1 (+ a b))) (nil a) (print a))
From: Pascal Bourguignon
Subject: Re: I see beauty!
Date: 
Message-ID: <87fzmbwrgp.fsf@thalassa.informatimago.com>
David Steuber <·············@verizon.net> writes:
> Oh! One other thing.  I really love the transition to bignums!  It
> does not take CMUCL long to overflow even a long long (64bit int on my
> arch) with this function.  A blink of the eye and you missed it.

Use CLISP for good bignums!


-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
From: Mario S. Mommer
Subject: Re: I see beauty!
Date: 
Message-ID: <fzk7bnt65o.fsf@cupid.igpm.rwth-aachen.de>
Pascal Bourguignon <····@thalassa.informatimago.com> writes:

> David Steuber <·············@verizon.net> writes:
> > Oh! One other thing.  I really love the transition to bignums!  It
> > does not take CMUCL long to overflow even a long long (64bit int on my
> > arch) with this function.  A blink of the eye and you missed it.
> 
> Use CLISP for good bignums!

He wasn't saying (afaict) that cmucl went to its knees, just that the
number grew bigger than 64 bit integers, and that it did so pretty fast.
From: Kenny Tilton
Subject: Re: I see beauty!
Date: 
Message-ID: <3EEC8CB0.7090803@nyc.rr.com>
David Steuber wrote:
> Kenny Tilton <·······@nyc.rr.com> writes:
>>When you are ready, you might drop us some feedback:
>>
>>    http://www.cliki.net/The%20Road%20to%20Lisp%20Survey
> 
> 
> I'll take a look at that.  Can you define ready?  I assume you mean
> that I can do more than work out a trivial little function without
> looking at the format for DO every two nanoseconds.

Well the unstated spirit of the survey is "how the hell do people end up 
liking/using/preferring a language they first encountered after its 
death?".

I suppose then that ready means one has gotten far enough that one is 
sure they like Lisp. I liked Prolog until I tried to use it in anger, 
which got me into the deeper chapters of the Prolog texts and I 
discovered my brain would not scale. Something like that.

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Everything is a cell." -- Alan Kay
From: Edi Weitz
Subject: Re: I see beauty!
Date: 
Message-ID: <871xxxjxv6.fsf@bird.agharta.de>
David Steuber <·············@verizon.net> writes:

> My first FORTRAN course for its first assignment posed the problem
> of writing a program to produce the Fibonacci sequence.
> Interestingly enough, that was also one of the first problems in a
> Pascal class I took.  Neither of those languages (or C) let me write
> something as brief as this:
> 
> (do ((a 1 b) (b 1 (+ a b))) ((> b 10000) a) (print a))
> 
> I'll admit it took me a few minutes to fully grok the DO syntax.
> And I thought C's for was pretty cool.
> 
> Now to try this thing with (> b 10000) replaced with nil. <eg>
> 
> I guess in Perl it would look something like this (using proper
> indentation):
> 
> for ($a=1,$b=1;$b<10000;$a=$b,$b+=$a) {
>   print "$a\n";
> }
> print "$a\n";
> 
> There is a problem though.  The Perl program gives the wrong
> results.  By the time we get around to incrementing $b, $a has
> already been given a new value.  This did not happen in the Lisp
> expression above.  DO was clever enough to use the *old* value of a.
> Or is that so clever?
> 
> In Perl or C, I would need an explicit temporary variable to
> preserve the old value of a so that I can use that to increment b.
> Lisp somehow did this behind my back.  I didn't even notice this
> until trying the same function in Perl.
> 
> So what happened?  Does CMUCL have a bug?  Is there an exception to
> left to right evaluation?  Was DWIM(X) invoked?

No, not a bug. Lisp _is_ so clever. Look up the difference between DO
and DO* in the Hyperspec and you'll see you can also have the "Perl
version" if you so wish.

This has nothing to do with left to right evaluation, by the way.

Cheers,
Edi.
From: Pascal Costanza
Subject: Re: I see beauty!
Date: 
Message-ID: <costanza-1DAC66.02423614062003@news.netcologne.de>
In article <··············@verizon.net>,
 David Steuber <·············@verizon.net> wrote:

> My first FORTRAN course for its first assignment posed the problem of
> writing a program to produce the Fibonacci sequence.  Interestingly
> enough, that was also one of the first problems in a Pascal class I
> took.  Neither of those languages (or C) let me write something as
> brief as this:
> 
> (do ((a 1 b) (b 1 (+ a b))) ((> b 10000) a) (print a))

> In Perl or C, I would need an explicit temporary variable to preserve
> the old value of a so that I can use that to increment b.  Lisp
> somehow did this behind my back.  I didn't even notice this until
> trying the same function in Perl.
> 
> So what happened?  Does CMUCL have a bug?  Is there an exception to
> left to right evaluation?  Was DWIM(X) invoked?

No, you have only just seen the light. ;)

The expressions are in fact evaluated left to right, it's only that the 
variables mentioned in the steps refer to the old values. You can get a 
different effect with do*. (see for example the HyperSpec or CLtL2 for 
details)

Here is what Guy Steele had to say about do:

"[...] The other constructs you mentioned (FOR, REPEAT, and WHILE) have
what I regard as an important flaw:  a reliance on side effects to
accomplish some part of the iterative process.  There is seldom any use
in stepping just one variable in an iteration; you want to step two or
more.  Because FOR, REPEAT, and WHILE (and for that matter DOLIST and
DOTIMES) each step at most one variable, it is necessary to have some
side effect in the body to get anything done.

DO is the only iteration construct we have (other than LOOP) that
encapsulates completely the notion of iteration: the iterative
transformation of a state (normally a compound state, therefore
consisting of two or more quantities) in such a way that an invariant is
maintained at each step, terminated when the state satisfies some
condition. The problem is not that DO has too many features, but that
each of the other iteration constructs is incomplete in a way that must
be patched up using side effects."

(as found at http://zurich.ai.mit.edu/pipermail/rrrs-authors/1986-July/000549.html )


Pascal
From: David Steuber
Subject: Re: I see beauty!
Date: 
Message-ID: <87d6hfj3i3.fsf@verizon.net>
Pascal Costanza <········@web.de> writes:

> In article <··············@verizon.net>,
>  David Steuber <·············@verizon.net> wrote:
> > So what happened?  Does CMUCL have a bug?  Is there an exception to
> > left to right evaluation?  Was DWIM(X) invoked?
> 
> No, you have only just seen the light. ;)

Quite a light it was too.  This is the first time I've appreciated
what Lisp can do for me.  DO did what I ment.  It did it without other
clutter that I would have put in the Perl or C code.

> Here is what Guy Steele had to say about do:

I agree with Guy.  I have done all sorts of ugly things with loops in
C and Perl.  break,continue/last,next anyone?  Multiple exit tests
inside the loop.  Yuck.

When I get to writing fancier expressions and functions, I am hoping
that reading Lisp will also grow easier.  With some exceptions, I can
read Perl or C as easily as I read English.  It will be nice when I
reach that level with Lisp.  I am infact hoping to exceed that level.
Lisp looks like a language that can be written clearer.  Certainly the
prefix notation is not a problem for me.  I've also messed around with
postfix on HP calculators and PostScript the Adobe programming
language.  Infix is just extra typing as far as I am concerned.

It comes down to understanding the words.

-- 
One Editor to rule them all.  One Editor to find them,
One Editor to bring them all and in the darkness bind them.

(do ((a 1 b) (b 1 (+ a b))) (nil a) (print a))
From: Thomas F. Burdick
Subject: Re: I see beauty!
Date: 
Message-ID: <xcvllw3kev4.fsf@famine.OCF.Berkeley.EDU>
David Steuber <·············@verizon.net> writes:

> When I get to writing fancier expressions and functions, I am hoping
> that reading Lisp will also grow easier.  With some exceptions, I can
> read Perl or C as easily as I read English.  It will be nice when I
> reach that level with Lisp.  I am infact hoping to exceed that level.
> Lisp looks like a language that can be written clearer.

It's even better than you think -- once you get the hang of Lisp, you
can read it as easily as *pseudo code*.  And I mean that literally --
one of my favorite Lisp techniques is to actually implement pseudo
code.  The first time I did this, I was implementing an algorithm that
a paper described using pseudo-Algol pseudo code; so, I built up the
macrology to implement the imaginary Algol-like language the pseudo
code was written in.  When I transcribed the code in the paper into an
s-expression form in my editor, I made a scene, I was so excited.
Ever since then, I've been kind of pissed when papers only give me
real code: pseudo code is so much nicer of a starting point, when
you've got Lisp!

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Kalle Olavi Niemitalo
Subject: Re: I see beauty!
Date: 
Message-ID: <87smqdt516.fsf@Astalo.kon.iki.fi>
David Steuber <·············@verizon.net> writes:

> In Perl or C, I would need an explicit temporary variable to preserve
> the old value of a so that I can use that to increment b.

Perl has a syntax for parallel assignment:

  for ($a=1,$b=1;$b<10000;($a,$b)=($b,$b+$a)) {
    print "$a\n";
  }
  print "$a\n";

This won't work with array variables, however.
From: David Steuber
Subject: Re: I see beauty!
Date: 
Message-ID: <877k7nj357.fsf@verizon.net>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> David Steuber <·············@verizon.net> writes:
> 
> > In Perl or C, I would need an explicit temporary variable to preserve
> > the old value of a so that I can use that to increment b.
> 
> Perl has a syntax for parallel assignment:
> 
>   for ($a=1,$b=1;$b<10000;($a,$b)=($b,$b+$a)) {
>     print "$a\n";
>   }
>   print "$a\n";
> 
> This won't work with array variables, however.

You're right.  I wonder why I didn't think to try that.  I do use Perl
idioms but I spend most of my time writing Perl by thinking in C and
then translating it.  Perhaps that is why I missed that little trick.

Mind you, it would take a bit more code in Perl to handle a longer
sequence.  It would be strange to see doubles suddenly printed instead
of ints.

The irony is, my last contract was all Perl work.  I did help someone
debug some C code because he didn't grok pointers and the need to use
free() (or rather, the RPC library equivilent).

-- 
One Editor to rule them all.  One Editor to find them,
One Editor to bring them all and in the darkness bind them.

(do ((a 1 b) (b 1 (+ a b))) (nil a) (print a))
From: Ng Pheng Siong
Subject: Re: I see beauty!
Date: 
Message-ID: <bcjc0a$get$1@mawar.singnet.com.sg>
According to David Steuber  <·····@david-steuber.com>:
> but I spend most of my time writing Perl by thinking in C and
> then translating it.

You're making it too hard for yourself.

I once compressed a 2000-line Perl program into 50 lines. It was really a C
program written in Perl; the original programmer reimplemented lots of
built-in Perl functionality (in that single program, no refactoring)
because she was thinking in C, not Perl.


-- 
Ng Pheng Siong <····@netmemetic.com> 

http://firewall.rulemaker.net  -+- Manage Your Firewall Rulebase Changes
http://www.post1.com/home/ngps -+- Open Source Python Crypto & SSL
From: David Steuber
Subject: Re: I see beauty!
Date: 
Message-ID: <87k7blgx71.fsf@verizon.net>
····@netmemetic.com (Ng Pheng Siong) writes:

> According to David Steuber  <·····@david-steuber.com>:
> > but I spend most of my time writing Perl by thinking in C and
> > then translating it.
> 
> You're making it too hard for yourself.
> 
> I once compressed a 2000-line Perl program into 50 lines. It was really a C
> program written in Perl; the original programmer reimplemented lots of
> built-in Perl functionality (in that single program, no refactoring)
> because she was thinking in C, not Perl.

I'm not quite _that_ bad ;-).  I do fairly well with Perl, but there
are those little bits that I forget I can do like the list to list
assignment that I could have done in the for loop.

For the most part, I have gotten to doing things in Perl instead of C
or C++ simply because I don't have to go through the compiling and
linking phase so that I can see results much sooner.  CPAN is full of
packages for doing things.  I've written very short screen scrappers
and proxies using LWP.

Mainly what I am talking about is the general syntax of Perl is very C
like.  It is not quite enough different to think properly in Perl
instead of C.  Still, it does affect how I code in Perl, and getting
further away from the C mindset would indeed be helpful.

I don't think you can get too much further away than Lisp.

-- 
One Editor to rule them all.  One Editor to find them,
One Editor to bring them all and in the darkness bind them.

(do ((a 1 b) (b 1 (+ a b))) (nil a) (print a))
From: Christopher Browne
Subject: Re: I see beauty!
Date: 
Message-ID: <bcna4t$l0u6s$2@ID-125932.news.dfncis.de>
After takin a swig o' Arrakan spice grog, David Steuber <·············@verizon.net> belched out...:
> Mainly what I am talking about is the general syntax of Perl is very
> C like.  It is not quite enough different to think properly in Perl
> instead of C.  Still, it does affect how I code in Perl, and getting
> further away from the C mindset would indeed be helpful.

Ah, but "syntax" is a fairly shallow thing.

Perl and Java and C++ and C all involve relatively "C-like" syntax,
but idiomatic programs are _very_ different in the respective
languages.

Notably, in Perl, "idiomatic" usage generally involves heavy use of
hashes and regexes, both of which are things that are, in all the
other languages on that list, shunted off to libraries that probably
aren't even widely used.

The use of hashes in Perl parallels the use of lists in Lisp.  Not in
that it is the same sort of data structure, but rather in that hashes
are ubiquitous and have a reasonably rich set of operators to
manipulate them, much as is the case for lists in Lisp.

A direct translation of C to Perl will lead to a program that is
probably crummy Perl.  (Some might think the observation of "crummy"
to be redundant; feel free...)
-- 
output = reverse("gro.mca" ·@" "enworbbc")
http://www.ntlug.org/~cbbrowne/advocacy.html
You shouldn't anthropomorphize computers; they don't like it.