Code block literals
Dave Benjamin
dave at 3dex.com
Wed Oct 8 23:01:02 EDT 2003
Mike Rovner wrote:
> Dave Benjamin wrote:
>
>>For instance, I always thought this was a cooler alternative to the
>>try/finally block to ensure that a file gets closed (I'll try not to
>>mess up this time... ;) :
>>
>>open('input.txt', { |f|
>> do_something_with(f)
>> do_something_else_with(f)
>>})
>>
>>Rather than:
>>
>>f = open('input.txt')
>>try:
>> do_something_with(f)
>> do_something_else_with(f)
>>finally:
>> f.close()
>
> "Explicit is better than implicit"
In that case, why do we eschew code blocks, yet have no problem with the
implicit invocation of an iterator, as in:
for line in file('input.txt'):
do_something_with(line)
This is not to say that I dislike that behavior; in fact, I find it
*beneficial* that the manner of looping is *implicit* because you can
substitute a generator for a sequence without changing the usage. But
there's little readability difference, IMHO, between that and:
file('input.txt').each_line({ |line|
do_something_with(line)
})
Plus, the first example is only obvious because I called my iteration
variable "line", and because this behavior is already widely known. What
if I wrote:
for byte in file('input.dat'):
do_something_with(byte)
That would be a bit misleading, no? But the mistake isn't obvious. OTOH,
in the more explicit (in this case) Ruby language, it would look silly:
open('input.txt').each_line { |byte|
# huh? why a byte? we said each_line!
}
I think this is important to point out, because the implicit/explicit
rule comes up all the time, yet Python is implicit about lots of things!
To name a few:
- for loops and iterators
- types of variables
- dispatching via subclass polymorphism
- coercion (int->float, int->long...)
- exceptions (in contrast with Java's checked exceptions)
- __magic_methods__
- metaclasses
- nested scopes (compared to yesteryear's lambda x, y=y, z=z: ...)
- list comprehensions
In all of the above cases (with a bit of hesitation toward the voodoo of
metaclasses) I think Python is a better language for it. On the other
hand, Perl's implicit $_ variable is a good example of the hazards of
implicitness; that can be downright confusing. So, it's not cut and dry
by any means.
If all you're saying is that naming something is better than not naming
something because explicit is better than implicit, I'd have to ask why:
a = 5
b = 6
c = 7
d = a + b
e = c / 2
result = d + e
return result
Is any better than:
...
return (a + b) + (c / 2)
To me, it's the same issue. Why should I have to name something that I'm
just going to return in the next statement, or pass as a parameter, and
then be done with it? Does that really increase either readability or
understandability? Why should I name something that I'm not going to ask
for later?
> Even your example clearly shows that try block is much more readable and
> understandable.
> That's why it's being considered evil by majority of python developers.
Readability is a moving target. I think that the code block syntax
strikes a nice balance between readability and expressiveness. As far as
what the majority of Python developers consider evil, I don't think
we've got the stats back on that one.
>>But the anonymous version still looks more concise to me.
>
> Python prioritize things diferently than other languages.
> It's not an APL. "Readability counts"
This is nothing like APL... if anything, it's like Smalltalk, a language
designed to be readable by children! I realize that APL sacrificed
readability for expressiveness to an uncomfortable extreme, but I really
think you're comparing apples and oranges here. List comprehensions are
closer to APL than code blocks.
Dave
More information about the Python-list
mailing list