What about an EXPLICIT naming scheme for built-ins?

Alex Martelli aleaxit at yahoo.com
Wed Sep 8 11:42:53 EDT 2004


Carlos Ribeiro <carribeiro at gmail.com> wrote:
   ...
> I'm thinking. Let me put it out this way: how can one "typecast" a
> generator? It seems to be conceptually different from "typecasting" an
> expression, a function, or variable, or a constant value.

Hmmm, OK, I guess, though I guess I still don't get it.


> After some pondering, I think I can rephrase my statement as:
> 
> "Extending your reasoning a little bit, list(anything) smells a
> typecast -- something that's used to convert a VALUE of one type into
> a VALUE of another type".
> 
> I prefer value in this context because the typecast really converts
> the value returned by the expression to another type. Did it sound
> right now?

It sounds perfect, except that for maximum clarity I would phrase it as
"make a new VALUE of one type from some VALUE of another (or the same)
type".  At least, that's how typecasting works in C++, which is the
widespread language in which you can use the sometypename(xyz) syntax;
it's calling the constructor of class 'sometypename' to make a new
instance of that class from whatever value 'xyz' stands for (if xyz's
type is already 'sometypename', it's making a new value of that type,
it's calling the copy constructor; otherwise it's calling some other
appropriate overloaded constructor depending on xyz's type).  In Java,
where typecasting must use the different syntax (typename)xyz, there is
no building of a new value with it -- to build a new value you use the
keyword 'new', as in "new typename(xyz)" (well, mostly you do, it's a
bit more complicated than that).

Python here uses the same syntax and semantics as C++, typename(xyz)
makes a new instance of that type, calling the constructor with the
value of xyz as the argument (there are no overloads involved, if any
typechecking on xyz's type is needed then typename's constructor must
deal with that).


> > Yes, it does read as a loop.  The funny thing is, I haven't seen the
> > same issues regarding sum(somenumbers()) -- which reads as a function
> > call, syntactically the same as list(somenumbers()), not as a loop.
> 
> Your example made me realize that the underlying problem is (again)
> the functional versus the imperative programming model. Let us think
> about it from "outside the box", looking at the words as someone who
> don't know Python yet:

OK, but if that someone thinks in terms of typecasting when he sees a
typename called with one argument, maybe that someone comes from C++,
and so presumably reads the call to the type as "make a new value of
that type", right?

> 
> -- sum(values()) is read as "sum all these values". It's a clear
> interpretation, both in functional and imperative terms.

Yep, though functionally it would be "THE sum OF all these values", noun
and verb happen to coincide here in the word 'sum'.  This is not a type
name, so the 'typecast' argument above can't apply, either.

> 
> -- list(values()) is read as "list all these values". The functional
> interpretation is easy -- it should return a list of all values. But
> the traditional definition of the word "list" in imperative
> programming is different -- it is associated with the action of
> printing out a list of values. Our problem should be stated in
> imperative terms as "put all these values into a list".

"Make a new list with these values", just like int(somestr) is "Make a
new int with this string", typename(xyz) is "Make a new instance of
typename with xyz", and so on.  At least, that's what I would expect
from the "typecast" mindset.

> 
> Many programmers were trained all their lives to think in the
> imperative way, not the functional one, and that's probably the real
> underlying problem. In a sense, *if* the list() builtin was named
> makelist() -- an imperative spelling of the same concept -- I think
> nobody would think twice before using it instead of the list
> comprehension version. (Please, I'm far from advocating to change the
> list() name -- the current name is fine and really ellegant -- I'm
> just trying to point out a difference in mental models).

There seem to be two issues which look mutually exclusive to me.
Reading the call to a type as a typecast, i.e. "make a(n instance of
this) type", should work just fine imperatively as well as procedurally,
the "make" verb being implied by the concept of typecast (well, not in
Java, but that uses a different syntax anyway).  Misreading 'list' as an
imperative verb rather than a typename would seem to preclude any
reading as "typecast".  I guess that people are excellent at having two
vague and contradictory mental models at the same time (the world is so
complicated than the ability to hold mutually contradictory beliefs has
no doubt always been pretty adaptive!-).

Well, thanks to you and Anna -- you've given me a lot of food for
thought.  I think I'll ask _her_ to edit the recipe about how to make a
list, which I had already written thinking of placement very early in
the first chapter of the 2nd edition of the Cookbook -- with this
discussion as a point of reference, plus her own thoughts in the matter,
she should be able to clarify this whole issue most usefully.


Thanks,

Alex



More information about the Python-list mailing list