"sins" (aka, acknowledged language problems)

Alex Martelli alex at magenta.com
Mon Dec 27 18:27:13 EST 1999


John Skaller writes:


> > But as soon as they published, and the book was
> > such an instant success, I started using their
> > design pattern names with abandon (with a biblio
> > reference in a comment, when I remembered:-).
> 
> I found the book interesting, and nothing
> more. I gained no enlightenment from it, other than

But it did make certain names for patterns widespread,
and therefore widely recognizable by-name.  You said
your recognition works by-pattern, not by-name; but,
surely, the existence and success of the book, and of
the whole patterns movement, argues for the existence,
within the ranks of our calling, of many who, like me,
much prefer verbal, by-name modes of thought.

An example of why experience is a good pre-requisite
for arrogance, I think.  A clever guy can make some
plausible-sounding argument for, or against, anything
(that was the whole point of the sophists: they taught
how to argue convincingly for whatever one wanted,
for a price, of course).  Experience has more potential
for solidity.

(It's also a point Stroustrup argues convincingly in
"Design & Evolution" -- how he put protected data
members in because he let himself be swayed by
good arguments, without experience backing them
up, and regretted it ever since...).


> the mild assertion than some patterns could not
> be encoded IN the language. It turns out this
> assertion is false in general -- it is language specific.

But for any language there will be patterns that
cannot be directly encoded in it -- else, doesn't
one fall into the classical barber-like paradoxes?
Goedel numbers, Turing halting problems, etc, etc?

Sure, for any finite set of patterns, you can find a
language encoding them all.  But, for any finitely
described language, it should be possible to show
that there are patterns it cannot encode, it seems
to me; that a meta-language, naming and discussing
emergent entities _about_ the language, is going
to be needed anyway.


> > widely known.  "condition and iftrue or iffalse"
> > is perceived by many as an unreadable way
> > to express a ternary operation, although IMHO
> > it has it all over C's "condition?iftrue:iffalse",
    [snip]
> You're right: are these really equivalent?

No, if the thing named "iftrue" can have a value
that is false by Python rules (the general idiom
of ternary selection that always works being:
    (condition and [iftrue] or [iffalse])[0]
whose readability I will not assert:-).  But, the
equivalence does hold in many practically
useful cases (wherever you know something
about "iftrue"'s 'truth value' being ok).

But the more we talk about it, the more readable
it becomes -- because the general acquaintance
with it grows.  Note: nothing in IT changes, yet
it "becomes" more readable... because, the
readability characteristic is part of the _language
games_ we play; it's about human beings, who
interact with language, not about language in a
vacuum (language has _no_ "characteristics in a
vacuum" -- "whatever we're talking about, we're
talking about the natural history of human beings" --
Wittgenstein's "Untersuchungen" being a good part
of my arrogance on _this_ specific issue;-).


> > > functions available, and (b) in except clauses,
> > > to make the exception available.
> > >
> > *blink* isn't that what sys.exc_info() is for...?
> 
> try: ...
> except TypeError, x: print x
> 
> Here, the 'x' is the actual exception object.
> It is not in global scope. It is not in local scope.
> At least, not in my implementation (Viper).
> It is available ONLY in the exception handler.
> At least, I assumed that: I never bothered to check this :-)

You're right, I'm outmatched in the arrogance game...:

>>> try:
...  raise IndexError, "hello"
... except IndexError, x:
...  print x
...
hello
>>> x
<exceptions.IndexError instance at 796140>
>>>

It seems to _me_, as a humble (:-) language
newbie, that this x is in no strange and magical
scope, but, rather, exactly in the scope I would
have expected it to be (here, typing things into
the interactive interpreter, the global one).

Ok, so, in Viper, it isn't.  Still, if your
assertion does not hold for "Python as we
know it", you might want to revise your
consequent assertion about the complexity
of Python's Locals-Globals-Builtins triad of
scopes...?

As I said originally, that simplicity need not
spoil your personal love affair with "properly
nested scopes".  Personally, I adore C++'s
NON-properly-nested namespaces -- ones
that I can strew around a large number of
disjoint header and source files -- but maybe
that's just me (well, I'm sure we can think of
another language which decouples namespaces
[modules] similarly, but, its name being a
4-letter word, I guess we won't sully this
newsgroup/list with it:-).


> > I particularly appreciated Java's abandonment
> > of classical rules for nested lexical scopes -- the
    [snip]
> Yeah, but the scopes still nest and control
> object lifetimes accordingly, right? The fact that

I'm not sure I would say they "control lifetimes",
given the peculiarities of Java garbage collection.

But, yes, in a limited sense -- if an object is
"visible" (accessible) it's guaranteed to be alive,
although the reverse is not true (it may or may
not be garbage collected, and if it is, its
finalizer may resurrect it anyway) -- I'm not
familiar enough with weak references in Java
to say how they affect this picture.

The nesting issue is also a bit complicated, since
(like in C++) a class that inherits or extends
acts a bit like a nested-but-not-lexically-so scope,
while a lexically-nested class acquires (in Java,
not in C++) different visibility (and, if I recall
correctly, _accessibility_ too).

> shadowing generates an error may have some
> advantages, but it also has disadvantages too:
> hiding supports 'cut and paste'.

And this is bad because...?

The "cut and paste" style of "code re-use" is a
blight (and I've done enough code inspections
of allegedly "production" code, and code built
by pretty brilliant people too, to make me
_very_ arrogantly sure of this specific issue:-).

If Java's "no hiding" rule really discourages it
(and I'm not sure it does -- somebody is sure,
alas!, to invent some "smart editor" that will
rename local variables on the fly as you paste
the code...!-), then I would count that as a
pretty major advantage.


> The ocaml people reckon that ocaml code
> is ten times more expressive than C/C++.
> (You can do the same job in 1/10th the number of lines).

I'll pass on this.  I think the record for "most
work done in fewest lines" is still with bad old
APL, at least for the kind of jobs it handled
best.  And, of course, right with it goes the record
for "most non-intentionally obfuscated code":-).


> in C++. The lack of proper lexical scoping makes
> templates more or less useless.

The authors of the Blitz++ library, and other
rabid users of templates, appear not to agree
with your opinion of their uselessness -- and
to have the experience to back their opinions
up.  (The _readability_ of those masses of
templates being a point to be argued quite
separately, of course; but, they *DO* seem
to make for a *powerful* compile-time code
generator engine -- Turing-complete, I hear).


> > If the wrappers are standardized, readability is no
> > problem.  
> 
> Most people think highly bracketted expressions
> are unreadable (eg LISP :-)

Yep, with the exception of rabid LISP'ers.

Would you thereby argue that the utter lack
of brackets in FORTH makes it the MOST
readable language?

Or, is it an issue of striking a happy medium?


> >And efficiency need not be, either; why
> > cannot you parse and optimize:
> > 
> >         for key,value in kv_enum(sequence):
> > 
> > just as easily as
> > 
> >         ifor key,value in sequence:
> 
> Well, in Python 'kv_enum' could be
> anything. It may default to a standard function,
> but the client can write:
> 
> kv_enum = myfunction

Yes, but, since Python's scopes are few:-),
cannot you _tell_ that kv_enum is used from
the __builtins__ dictionary, if it is not
assigned in the other two namespaces?
If it _is_ assigned, no optimization, sure.

I may not have conceptualized Python's
compilation process correctly enough, but
isn't this what it already does to distinguish
local vs global identifiers?  If assigned
anywhere within local scope, it's deemed
to be a local identifier, else, a global or
built-in -- at least (switching rapidly into
humble mode again -- not enough experience
to back up arrogance here:-), that's how I
had mentally modeled the process.

Of course, it _would_ help if the __builtins__
namespace was locked... but, it would not
offend my aesthetics if the language specs
just said, "if you assign to any member of
__builtins__, it is unspecified whether the
assignment affects the script's semantics",
much as is currently specified for assignment
to members of locals() -- i.e., such hackery
would be specified to be a low-level, version
specific dirty trick, not guaranteed not to
break on any future compiler releases.

This would allow similar optimizations, if
desired, on any frequent and important
idiom involving built-in functions -- an
important general aspect, it seems to me.

> 
> This cannot be done for the 'ifor' form, since 'ifor'
> is a keyword.
>  
> > >       Quite a lot of the time, you CAN provide the y:
> > > using functional programming with map and reduce etc.
> > >
> > Yep -- and O-O wrappings work for it, too.
> 
> The difference is that the 'OO' wrappings, in general,
> cannot be localised. This leads to spagetti.

I _could_ "localize" (make a local copy of the class 
definition), but, why ever would I WANT to?  I don't 
feel any need to "localize" such language aspects as 
"and", "or", etc -- and you just pointed out that the 
"ifor" you want to implement could not be "localized" 
(in fact, it could not be redefined at all by the user,
neither locally nor otherwise) as an _advantage_.

That's not spaghetti (another issue on which I feel
superbly confident -- you see, being Italian, I have
_nothing_ to learn about pasta from an Australian...
hey, would you let ME teach you about kangaroos?-)
[I should notice in passing that I love Australia, that
my favourite hat is made in Australia, _and_ that 
my regular partner on OKbridge lives in Canberra --
just to prevent a lynch mob forming Down Under to
come after me... or would the mention of Canberra 
just make things even worse for a New South Welsh...?-)]


> > > This works well in functional programming languages,
> > > but it doesn't work nearly as well in python
> > > What I mean  is, the 'y' becomes so cluttered the reader
> > > isn't sure what is happening.
> > >
> > Why would it be less cluttered in a functional PL?
> 
> At least in ML languages, function calling does
> not require brackets. Of course, you still need them
> to override the default precedence. :-(

The only language I've used extensively, where function
calling does not require parentheses, is the 4-letter
language above alluded to, which shall here remain
nameless.  (Well, and Forth, too, but "that was in 
another country", and, besides, the machine I ran 
_that_ on is dead).  I must say that the usage one
finds there does not particularly argue for the lack
of parentheses enhancing readability, but that is
perhaps not a fair test-bed for such a quality:-).


Alex






More information about the Python-list mailing list