Code block literals

Dave Benjamin ramen at lackingtalent.com
Thu Oct 9 13:41:17 EDT 2003


In article <mxehb.190229$hE5.6409803 at news1.tin.it>, Alex Martelli wrote:
> Dave Benjamin wrote (answering Mike Rovner):
>    ...
>>> "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)
> 
> I don't see that there's anything "implicit" in the concept that a
> special operation works as indicated by its syntax.  I.e., I do not
> find this construct any more "implicit" in the first line than in
> its second one, which is the juxtaposition of a name and a pair of
> parentheses to indicate calling-with-arguments -- and alternatives...

What's implicit to me is that the use of an iterator is never specified.
For instance, we could (and I'm *not* suggesting this) do this:

iterator = file('input.txt')
while iterator.has_next():
    line = iterator.next()
    do_something_with(line)

> This has nothing to do with "eschewing code blocks", btw; code blocks
> are not "eschewed" -- they are simply syntactically allowed, as
> "suites", only im specific positions.  If Python's syntax defined
> other forms of suites, e.g. hypothetically:
> 
> with <object>:
>     <suite>
> 
> meaning to call the object (or some given method[s] in it, whatever)
> with the suite as its argument, it would be just as explicit as, e.g.:
> 
> for <name> in <object>:
>     <suite>
> 
> or
> 
><object>(<object>)

This would be an interesting alternative, but it's back to being a special
case, like Ruby has. I think it'd be more flexible as a literal that returns
a callable.

>> 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
> 
> You could do so even if you HAD to say iter(<object>) instead of
> just <object> after every "for <name> in" -- it wouldn't be any
> more "explicit", just more verbose (redundant, boiler-platey).  So
> I do not agree with your motivation for liking "for x in y:" either;-).

Well, let's just say I've been on the Java side of the fence for a little
while, and it has redefined my personal definition of explicit. One of the
reasons Python code is so much smaller than Java code is that a lot of
things are implicit that are required to be explicit in Java. I see this as
a good thing.

>> there's little readability difference, IMHO, between that and:
>> 
>> file('input.txt').each_line({ |line|
>>      do_something_with(line)
>> })
> 
> Not huge, but the abundance of ({ | &c here hurts a little bit.

Well, we all __pick__ our __poisons__...

>> 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!
>> }
> 
> Here, you're arguing for redundance, not for explicitness: you are claiming
> that IF you had to say the same thing more than once, redundantly, then
> mistakes might be more easily caught.  I.e., the analogy is with:
> 
> file('foo.txt').write('wot?')
> 
> where the error is not at all obvious (until runtime when you get an
> exception): file(name) returns an object *open for reading only* -- so
> if you could not call file directly but rather than do say, e.g.:
> 
> file.open_for_reading_only('foo.txt').write('wot?')

Nah, I'm not arguing for redundancy at all. I'm saying that there is some
voodoo going on here. When the *constructor* for a file object behaves like
a generator that loops over newline-delimited lines of a text field, doesn't
that seem like it's been specialized for a particular domain in an unobvious
way? Why lines? Why not bytes, words, unicode characters? I mean, it's more
convenient for people that do a lot of text processing, but I don't see
anything specific to text or lines in the phrase "file('foo.txt')". That's
all I'm saying.

>> 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
> 
> Already addressed above: nothing implicit there.

Likewise, and I still disagre... =)

>>    - types of variables
> 
> There are none, so how could such a nonexisting thing be EITHER implicit
> OR explicit?  Variables don't HAVE types -- OBJECTS do.

The very fact that variables to not have types, and following that, that
variables do not have manifest types, is an example of implicit being
chosen over explicit. I know your argument, and I understand that Python
variables are Post-It sticky notes and all of that, but please, just try to
look at it from a non-Python-centric perspective. Other languages (like C++,
which I hear you are vaguely familiar with ;) require you to be explicit
about what type of thing you're defining and sending where. Python does not.
This is one of its strengths, because it allows for ad-hoc interfaces and
polymorphism without a lot of boilerplate.

> Etc, etc -- can't spend another 1000 lines to explain why your "lots of
> things" do not indicate violations of "explicit is better than implicit".

They're not *violations*. Correct me if I'm wrong, but the Zen of Python is
not the LAW! It's a poem! It's very beautiful, very concise, inspiring, and
thoughtful, but it's not the 10 commandments! I just get very tired of every
idea getting shot down because of some rule from Tim Peters. I really don't
think he intended for it to be used to prove the validity of ideas.

The implicit/explicit thing is one of the most abused, in my opinion,
because it can quite frankly be used to shut down any attempt at creating
abstraction. In fact, for that reason alone, I'm tempted to say "Implicit is
better than explicit". Say what you want, not how you want it. Be abstract,
not concrete.

>> 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:
> 
> Sometimes it is (to avoid perilous nesting), sometimes it isn't (to
> avoid wanton naming).  I generally don't mind naming things, but it IS
> surely possible to overdo it -- without going to the extreme below,
> just imagine a language where ONLY named argument passing, and no use
> of positional arguments, was allowed (instead of naming arguments being
> optional, as it is today in Python).

I don't have to imagine. It's called Smalltalk, and also (to some extent)
Tcl/Tk. Even Tkinter seems to be named-argument only. It's not that bad.
I still like positional parameters, though.

> If a Pythonic syntax can't be found to solve ALL use cases you've
> raised, then the "balance" may be considered not nice enough to
> compensate for the obvious problem -- a serious case of MTOWTDI.

That's another argument for another day. ;)

>>> 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! 
> 
> Cite pls?  I knew that Logo and ABC had been specifically designed
> with children in mind, but didn't know that of Smalltalk.

http://ei.cs.vt.edu/~history/GASCH.KAY.HTML
http://www.cosc.canterbury.ac.nz/~wolfgang/cosc205/smalltalk1.html
http://www.cs.washington.edu/homes/dugan/history.html

>> 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.
> 
> As an ex-user of APL (and APL2) from way back when, I think you're
> both talking through your respective hats: neither list comprehensions
> (particularly in the Python variation on a Haskell theme, with
> keywords rather than punctuation) nor code blocks resemble APL in the least.

Well, it was a rough analogy, and I've never done any APL myself, but here's
my justification, FWIW:

 - APL provides syntactical constructs for high-level array processing
 - List comprehensions do this also
 - Code blocks have nothing inherently to do with array processing

But I agree that neither resemble APL as I've seen. I guess it's like saying
a carrot is more like APL than a rutabega.

Dave

-- 
.:[ dave benjamin (ramenboy) -:- www.ramenfest.com -:- www.3dex.com ]:.
: d r i n k i n g   l i f e   o u t   o f   t h e   c o n t a i n e r :




More information about the Python-list mailing list