[Python-3000] iostack and Oh Oh
janssen at parc.com
Sun Dec 3 22:53:58 CET 2006
Phillip Eby writes:
> Why do you *need* to know? The truth is that you don't need to know if
> something is "a mapping", you need to know if it does what you want it to
> do. And what you want a "mapping" to do may not be the same as what
> somebody else wants a "mapping" to do, which then leads to problems if two
> libraries are deciding what to do with an object based on it being "a mapping".
That's when they'd use two different interfaces, of course.
> The thing you're defining as a solution, is actually a source of more
> problems. At least when the concept of "mapping" is expressed verbally,
> everybody *knows* that the term is fuzzy. Reifying it into an object
> doesn't actually eliminate the inherent fuzziness -- which is why I
> proposed a fuzzy interface implementation, btw.
Phillip, now I'm just confused. I thought you were advocating
changing Python into a really functional language and adding a generic
function mechanism, but now I hear you saying that Python modules
should, practically speaking, always be badly documented. For
instance, when I see a library function (or method) documented as
foo (m, f)
where "m" is a mapping and "f" is a file...
I don't have a clue what I need to pass as "m" and "f". Will the
function exception on me if I don't implement "values()" in "m"? Does
"f" need to be seekable, or will it have to support "fileno()"? How
many of the three different calling modes to "update()" does "m" have
to support? Does "__setitem__" need to be supported? What I'd like
to see as documentation is more along the lines of
foo (types.Mapping m, (types.SeekableStream, types.BinaryOutputStream) f) => types.Integer
and *no* human-readable text giving an inaccurate and incomplete
description of the parameters. If I could get these kinds of
assurances (on return results as well as on parameters), I think some
of my need for type introspection would disappear. Someone suggested
the name "contracts" for this, which I think (Eiffel aside) fits very
well. It's a contract between the writer of the calling code and the
writer of the code being called about what gets passed in and what
gets returned. There are no pre-condition/post-condition tests in the
Eiffel sense (though there may be invariants), no static type checking
in the Java sense -- just a well-understood agreement.
> If you want to be specific, refer to operations.
I agree that in some Utopian wonderland, that would (for the most
part) fix the problem. But the reality is that (a) we don't have good
ways of talking about collections of operations, and (b) most
programmers would rather write code than write documentation, and (c)
lots of library implementors don't really know what operations are
required because they themselves call poorly documented library
functions. So few if any writers are actually going to *get* specific
by referring to operations. That's why interface names help; they let
us refer to bundles of operations, as well as any semantics for that
bundle that aren't captured by the operation signatures, in a few
keystrokes. And because of (b), documentation that *looks* like code
is more likely to be written.
> So, we should have fuzzy interfaces, that reflect our fuzzy notions of
> "mapping", and do not require that an object implement the whole of an
I think that's an unworkable idea, and (sorry) I think it really holds
Python back. People's "fuzzy notions" of what's in a "mapping"
differ; but code has a very unforgiving idea of what it wants. What
we need are precise ways of talking about very exact specifications,
that still work well with the fuzziness of ordinary human thought.
> just like our fuzzy notion of "bird" does not require that all
> birds fly, even though most of them do.
That's why "big" interfaces are composed through inheritance of
smaller interfaces, just as the bird class "Aves" contains more than
two dozen orders (and more than 8,000 species).
More information about the Python-3000