What's better about Ruby than Python?

Kenny Tilton ktilton at nyc.rr.com
Thu Aug 21 13:40:25 EDT 2003


Andrew Dalke wrote:
> Kenny Tilton
> 
>>Lisp hashtables can key off any Lisp datum, but...
> 
> 
> Bear with my non-existant Lisp knowledge
> 
> Suppose the code is modified.  How does the hash table
> get modified to reflect the change?  Written in Python,
> if I have
> 
> a = (1, 2, (3, [4, 5]))

Lisp is sick. From the hyperspec on make-hash-table, the test for 
lookups can be "eq, eql, equal, or equalp. The default is eql." EQUAL 
would work for this case. EQL just looks at object identity.

> 
> I can't hash it because someone could come by later
> and do
> 
> a[2][1].append(6)
> 
> so the hash computation and test for equality
> will give different results.
> 
> 
>>The next step would
>>have been to determine when the closure had best re-execute the code
>>body to see if the world had changed in interesting ways, but that is a
>>big step and requires dependency tracking between cells.
> 
> 
> Ahhh, so the Python code was comparable in power without
> using macros?

No, it was completely different, as per my earlier post. What you did is 
what is called MEMOIZE (not part of CL, but I saw some Perl refs pop up 
when I googled that looking for Paul Graham's memoize code from On 
Lisp). My code just calculates once ever! That is why it needs me to 
give another talk in which I add dependency tracking and state change 
propagation. And even then it does not memoize, tho you have me thinking 
and I could certainly make that an option for Cells that need it. Kind 
of rare, but it would be a shiniy new bell/whistle for the package.

No, to match the power of my code you need to do:

     (let ((b (make-instance 'box
                  :left 10
                  :right (c? (* 2 (left self)))))
       (print (list (left b) (right b)))

and see (10 20).

You need to then change the source above to say (c? (* 3 (left self))) 
and see (10 30). It should be supported by no more than

(defmodel box ()
     (left...)
     (right...))

Macros are not functionality, they are about hiding the wiring/plumbing 
behind neat new hacks, in a way functions cannot because they jump in at 
compile time to expand user-supplied code into the necessary 
implementing constructs.


> Could the same code be written in Lisp using an approach
> like I did for Python? 

Download Paul Graham's On Lisp, he has a macro in there that hides all 
the plumbing you used for cacheing. :) Look for "Memoize".

> How would a non-macro solution look
> like? 

(let ((cache :unbound))
   (lambda (self)
     (if (eq cache :unbound)
         (setf cache (progn (+ 10 (left self))))
       cache)))

> What's the advantage of the macro one over the non-macro
> one?  Just performance?

Again, arranging it so necessary wiring is not cut and pasted all over, 
cluttering up the code to no good end, and forcing all the code to be 
revisited when the implementation changes. ie, They are just like 
functions, except they operate at compile time on source code. The 
bestest I could do without macros would be:

(make-instance 'box
     :left (c? (lambda (self)
                 (+ 2 (right a)))
     ....

Where C? becomes a function which returns an instance which has a slot 
for the cache. But then, without macros, I have to hand-code the setters 
and getters on every such slot. My defmodel macro writes those accessors 
silently.

You know, with all due respect, the question really is not if macros are 
useful/powerful. They are, and I think even you conceded that. Forgive 
me if I am mistaken. At their most powerful they expand into multiple 
top-level definitions and even stash info globally to assist 
development, such as being able to inspect the source of a closure at 
debug-time. They run at compile time and get a look at the source,a nd 
can do interesting things functions cannot.

The anti-macronistas are better off with the argument, hey, if you want 
Lisp, use Lisp. Let's keep it simple here. the question for you all is 
how far you want to take Python.

Since there already is a Lisp -- stable, compiled, ANSI-standardized, 
generational GC, etc, etc -- it would be easier to generate FFI bindings 
for needed C libs than to play catch up against a forty year lead.


-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker





More information about the Python-list mailing list