Flat-schmat! [was Re: Python syntax in Lisp and Scheme]

Kenny Tilton ktilton at nyc.rr.com
Sun Oct 5 08:27:47 EDT 2003


Andrew Dalke wrote:

> Still have only made slight headway into learning Lisp since the
> last discussion, so I've been staying out of this one.  But
> 
> Kenny Tilton:
> 
>>Take a look at the quadratic formula. Is that flat? Not. Of course
>>Python allows nested math (hey, how come!), but non-mathematical
>>computations are usually trees, too.
> 
> 
> Since the quadratic formula yields two results, ...

I started this analogy, didn't I? <g>

I expect most
> people write it more like
> 
> droot = sqrt(b*b-4*a*c)  # square root of the discriminate
> x_plus   = (-b + droot) / (4*a*c)
> x_minus = (-b - droot) / (4*a*c)

Not?:

(defun quadratic (a b c)
   (let ((rad (sqrt (- (* b b) (* 4 a c)))))
     (mapcar (lambda (plus-or-minus)
               (/ (funcall plus-or-minus (- b) rad) (+ a a)))
       '(+ -))))
	
:)

> 
> possibly using a temp variable for the 4*a*c term, for a
> slight bit better performance.

Well it was a bad example because it does require two similar 
calculations which can be done /faster/ by pre-computing shared 
components. But then the flattening is about performance, and the 
subject is whether deeply nested forms are in fact simpler than 
flattened sequences where the algorithm itself would be drawn as a tree. 
So the example (or those who stared at it too hard looking for 
objections <g>) distracted us from that issue.

> But isn't that flattening *exactly* what occurs in math.  Let me pull
> out my absolute favorite math textbook - Bartle's "The Elements
> of Real Analysis", 2nd ed.

Oh, god. I tapped out after three semesters of calculus. I am in deep 
trouble. :)

> 
> I opened to page 213, which is in the middle of the book.
> 
>    29.1  Definition.  If P is a partition of J, then a Riemann-Stieltjes sum
> of f with respect to g and corresponding to P = (x_0, x_1, ..., x_n) is a
> real
> number S(P; f, g) of the form
> 
>                            n
>      S(P; f, g) = SIGMA  f(eta_k){g(x_k) - g(x_{k-1})}
>                          k = 1
> 
> Here we have selected number eta_k satisying
> 
>   x_{k-1} <= eta_k <= x_k for k = 1, 2, ..., n
> 
> There's quite a bit going on here behind the scenes which are
> the same flattening you talk about.  For examples: the definiton
> of "partition" is given elsewhere, the notations of what f and g
> mean, and the nomenclature "SIGMA"

<snip another good example>

> In both cases, the equations are flattened.  They aren't pure trees
> nor are they absolutely flat.  Instead, names are used to represent
> certain ideas -- that is, flatten them. 

No! Those are like subroutines; they do not flatten, they create call 
trees, hiding and encapsulating the details of subcomputations.

We do precisely the same in programming, which is part of why flattening 
  can be avoided. When any local computation gets too long, there is 
probably a subroutine to be carved out, or at least I can take 10 lines 
and give it a nice readable name so I can avoid confronting too much 
detail at any one time. But I don't throw away the structure of the 
problem to get to simplicity.

> .. You judge the Zen of Python
> using the Zen of Lisp.

Hmmm, Zen constrained by the details of a computing language. Some 
philosophy! :) What I see in "flat is better" is the mind imposing 
preferred structure on an algorithm which has its own structure 
independent of any particular observer/mind.

I am getting excellent results lately by always striving to conform my 
code to the structure of the problem as it exists independently of me. 
How can I know the structure independently of my knowing? I cannot, but 
the problem will tell me if I screw up and maybe even suggest how I went 
wrong. I make my code look like my best guess at the problem, then if I 
have trouble, I try a different shape. I do not add bandaids and patches 
to force my first (apparently mistaken) ideas on the problem. When the 
problem stops resisting me, I know I have at least approximated its 
shape. Often there is a "pieces falling into place" sensation that gives 
me some confidence.

Lisp has both SETF and "all forms return a value", so it does not 
interfere in the process. In rare cases where the functional paradigm is 
inappropriate, I can run thru a sequence of steps to achieve some end. 
Lisp stays out of the way.

Python (I gather from what I read here) /deliberately/ interferes in my 
attempts to conform my code to the problem at hand, because the 
designers have decreed "flat is better". Python rips a tool from my 
hands without asking if, in some cases (I would say most) it might be 
the right tool (where an algorithm has a tree-like structure).

I do not think that heavy-handedness can be defended by saying "Oh, but 
this is not Lisp." It is just plain heavy-handed.

kenny

"Be the ball."
       - Caddy Shack








More information about the Python-list mailing list