From: Gabe Garza
Subject: Re: Common Lisp and the Little Schemer
Date: 
Message-ID: <k7wyz0ju.fsf@kynopolis.org>
······@hushmail.com writes:

> I'm now learning CL with PAIP after having read 'The Little Schemer'

Two superb choices. :)

> and 'The seasoned Schemer'. My Scheme background is giving me some
> trouble, because of the differences in what is considered an atom

An atom is anything that is not a CONS cell.  That is, not a list
or a "dotted pair."

> and null/null?,

In Common Lisp, NIL and '() are the same object.  The empty list is
the symbol NIL, and vica-versa.  In Scheme, null? returns true if its
argument is the empty list that is, ().  In Common Lisp, NULL returns
true if its argument is either '() or NIL, because they are the same
thing.  My Scheme is rusty, so forgive or correct any mistakes...

> 
> For those who haven't read the Little Schemer, 'The first
> commandment' is a template for functions that work on lists. This is
> the original text:
> 
> 'When recurring on a list of atoms, lat, ask two questions about it:
> (null?  lat) and else.[...]When recurring on a list of
> s-expressions, l, ask three questions about it: (null? l), (atom?
> (car l)) and else"
> 
> This pattern doesn't seem to be common in PAIP. Is this
> 'commandment' recommended in CL?  What's the ususal way of doing
> this in CL?

  In general, iteration is far more common in CL then in Scheme.  Part
of this is the culture and part of this is that CL provides a very
rich set of iteration operators, whereas Scheme only provides the
somewhat hairy DO (IIRC: I'm rusty on Scheme) (apologies to any DOphiles
out there :)).

   As a simple example: if you want to write a function to sum the squares
of a list, in Scheme you might write

(define (sum-squares lst)
  (if (null? lst) 
      0 
      (+ (* (car lst) (car lst))
         (sum-squares (cdr lst)))))

Whereas in Common Lisp you might write

(defun sum-squares (list)
  (loop for number in list sum (* number number)))

or

(defun sum-squares (list)
  (let ((sum 0))
    (dolist (number list)
      (incf sum (* number number)))
    sum)) 

or

(defun sum-squares (list)
  (reduce #'+ (mapcar (lambda (a) (* a a)) list)))   

[this is applicative and not iterative, but still a style you'll
 see used]

Common Lisp's iteration forms are documented in section 6.2 of the
HyperSpec.  If you haven't yet downloaded it, you can get it at:

http://www.xanalys.com/software_tools/reference/HyperSpec/index.html

Just because iteration is less common doesn't mean recursion isn't
used.  Some people prefer it stylistically, and there are some
algorithms where recursion is either the only way to express it (short
of using a stack to simulate recursion) or the cleanest way to.
"Recurring on a list of S-expressions" often falls under the latter
condition.

> After going through the little schemer, those 'commandments'
> (function templates) are a bit 'hardwired' and are confusing me
> while trying to translate them into CL. Should I get rid of this
> Scheme bagage or is it still valid in CL?

   Yes. :)

   You should get rid of the Scheme baggage.  It is valid in CL, but it's 
rarely used.
   
Gabe Garza

From: Barry Margolin
Subject: Re: Common Lisp and the Little Schemer
Date: 
Message-ID: <_iTH7.6$uB6.4595@burlma1-snr2>
In article <··································@4ax.com>,
 <······@hushmail.com> wrote:
>The Little Schemer recommends to write an internal recursive function that has
>expr as a free variable (to avoid passing it over and over).  I tried it, and
>apparentley it's not a good idea in CL, since the performance is worse.
>Weird... 

Did you compile your function?  If you did, I wouldn't expect it to make a
big difference if you compile.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Barry Margolin
Subject: Re: Common Lisp and the Little Schemer
Date: 
Message-ID: <s6VH7.10$uB6.4894@burlma1-snr2>
In article <··································@4ax.com>,
 <······@hushmail.com> wrote:
>No, not a big one, but the difference was exactly the opposite that I had
>expected: the function that passed that 'constant' parameter was faster... 

When you use a free variable in an internal function, a common
implementation technique is to pass an environment object as an implicit
parameter.  Accessing the free variable requires indirecting through this
environment, whereas normal parameters can be accessed directly in the
stack frame.  So there's often a little more overhead involved in this.

A clever compiler might notice that the free variable is never modified,
which would allow some optimization.  But if you're seeing slower
performance, it's likely that it doesn't perform this optimization.  In
Scheme, if you were to write the internal function tail-recursively, the
optimization would occur naturally as a result.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Barry Margolin
Subject: Re: Common Lisp and the Little Schemer
Date: 
Message-ID: <5cYH7.16$uB6.5517@burlma1-snr2>
In article <··································@4ax.com>,
 <······@hushmail.com> wrote:
>The function wasn't tail recursive (see below). Anyway, is this something that

You didn't include anything below.

>should be taken into account (performance wise) when using common lisp, or
>better forget it? :)

Unless the function is a performance bottleneck, who cares?  Clarity is
usually more important than wringing every little bit of performance.
Also, the performance impact is likely to be very dependent on the
implementation, so it might be better to do it one way in some
environments, and the other way in others.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.