merits of Lisp vs Python

André Thieme address.good.until.2006.dec.22 at justmail.de
Mon Dec 11 08:19:23 EST 2006


Steven D'Aprano schrieb:
> On Sat, 09 Dec 2006 14:57:08 -0500, Bill Atkins wrote:
> 
>> Paul Rubin <http://phr.cx@NOSPAM.invalid> writes:
>>
>>> There is just not that much boilerplate in Python code, so there's
>>> not so much need to hide it.
>> Well, of course there is.  There are always going to be patterns in
>> the code you write that could be collapsed.  Language has nothing to
>> do with it; Lisp without macros would still be susceptible to
>> boilerplate.
>>
>> Here's a concrete example:
>>
>>   (let ((control-code (read-next-control-code connection)))
>>     (ecase control-code
>>       (+break+
>>         (kill-connection connection)
>>         (throw :broken-by-client))
>>       (+status+
>>         (send-status-summary connection))
>>       ((+noop+ +keep-alive+))))
>>   ;; +X+ indicates a constant
> 
> Eight lines, excluding the comment, and it doesn't handle the case where
> control-code is not one of +break+, +status+, +noop+ or +keep-alive+,
> although the ecase macro does. And how many lines of code is ecase?
> 
>> All of that
>> boilerplate is handled by the macro.  In Python, I would need to do
>> something like:
>>
>>   control_code = connection.read_next_control_code()
>>   if control_code == +break+:
>>     connection.kill()
>>     throw blah
>>   else if control_code == +status+:
>>     connection.send_status_summary()
>>   else if control_code == +noop+ || control_code == +keep_alive+:
>>   else:
>>     error "CONTROL_CODE fell through conditional cascade; was not one of +BREAK+, +STATUS+, +NOOP+, +KEEP_ALIVE+"
> 
> Your Python syntax is rather wonky, but that's incidental.
> 
> Nine lines, including handling the case where control_code is none of the
> four constants. Ten if you add the "pass" statement that it actually
> needs. And it is completely self-contained, with no external functions or
> macros to understand.

Counting source lines is not the important thing. Look at the complexity
and the number of tokens.
The Lisp code is easier, because it is more abstract. You are closer in
saying what you want.

Counting tokens:
(let ((control-code (read-next-control-code connection)))   4
   (ecase control-code                                       2
     (+break+                                                1
       (kill-connection connection)                          2
       (throw :broken-by-client))                            2
     (+status+                                               1
       (send-status-summary connection))                     2
     ((+noop+ +keep-alive+))))                               2
                                                          ======
                                                            16


control_code = connection.read_next_control_code()              4
if control_code == +break+:                                     4
   connection.kill()                                             2
   throw blah                                                    2
else if control_code == +status+:                               4
   connection.send_status_summary()                              2
else if control_code == +noop+ || control_code == +keep_alive+: 8
else:                                                           1
   error "CONTROL_CODE fell through conditional cascade;         2
       was not one of +BREAK+, +STATUS+, +NOOP+, +KEEP_ALIVE+"
                                                              ======
                                                                29
plus a "pass", would make 30 vs 16  "Brain-units".


André
-- 



More information about the Python-list mailing list