Re: Lots o' Questions

Jim Roskind (jar@infoseek.com)
Wed, 20 Jul 1994 23:16:52 -0700

I liked ;-o some of the questions, so I decided to chime in with my
perception of some of the answers. I'm sure I'll be vanquished by a
clever guru, but at least I'll get to toss my opinions into the fray.
In addition, if my opinions are wrong, I'll learn something. :-) :-)
(i.e., double smiley).

> From: Craig Lawson <claw@rahul.net>
> Date: Wed, 20 Jul 1994 18:31:04 GMT
>
> 1) Why can't some functions be applied to immutable types?
> Example: Applying list methods "index" or "count" to strings.
> Even more to the point, defining "remove", "reverse" or "sort" for
> strings such that they return a new strings.

There are three classes of issues here. For methods such as "remove,"
"reverse," or "sort," the defined semantics require an "in place"
activity. Alas, strings are immutable. Hence there is no way to
achieve the required semantics on the given type. You *could* define
some other functions, but these methods are (by definition)
impossible on immutable type.

With regard to 'index,' I'd note that there is an "index function"
that can be applied to strings. IMHO, it would be very nice to have
*both* a function and a method version of such a procedure, so that I
would not have to look up *which* version (method vs function) was
appropriate for which type (string vs array) for each of the possibly
confusing operations (example: length, index, etc.). There might be
some underlying problem with implementing such, and I'm sure that if
there is, then someone will tell me what it is ;-).

Finally, with regard to count, I have to punt, as I don't have the
foggiest idea why this functionality is not provided for strings
(though I'd guess that demand drives feature implementation :-), and
rightly so ).

> 2) Why make strings immutable in the first place?

I think the big advantage of immutable types comes from their
performance capabilities. Knowing that a string is immutable makes it
easy to lay it out at construction time (fixed and unchanging storage
requirements). I *think* this is also fundamentally the distinction
between tuples and arrays. There are lots of other strategies for
creating a "string class," but this seems to be a reasonably sound
approach. Although a C programmer is unsurprised to see string
objects change without the address changing, it seems *very*
reasonable to consider strings to be as "elemental" as numbers. No
amount of activity will change the value 8 to anything else, and in
Python, no amount of activity will change the string "eight" to
anything else.

> 3) Why aren't all types treated as objects, (i.e. strings)?
> Why can't I write: "a string".length()

Darn good question. No good answer from me. :-). (... and I've asked
this question before). See paragraph two of my answer to question 1
above (re: index()). This is really the same issue.

> 4) Why can't I descend from built-in classes? Why can't I derive a
> class from the built-in "file" class? It would save me the trouble of
> creating a wrapper class to add functionality (like a "getchar()"
> type function.

You're over my head here. Time for a guru to answer ;-).

> 5) Why do scoping rules require an explicit scope specification for
> everything except: self.<class_var> ? Example:
> class my_class:
> i = 1
> def f(self):
> self.j = self.i + 1
>
> Here, "j" is an instance variable and "i" is a class variable,
> shared among all instances of the class. They are accessed with
> the same syntax. Why?

Actually, they don't have to use the same syntax. You could have
written:

class my_class:
i = 1
def f(self):
self.j = my_class.i + 1

What you used when you typed "self.i" was something akin to
inheritance, wherein names in the class for "my_class" are scanned
after names in the dictionary for the current instance of "self." In
fact, if you used *your* code definition, and then ran:

temp = my_class
temp.i = 99
temp.f()

You would find that "temp.j" evaluates to 100! If you used my code
definition, you would have had the expected "temp.j" evaluating to 2.
Critical is that rather than some sort of "lexical scoping," the
lookup for "self.i" was done at run time in the dictionaries present
for the instance "self."

> 6) Why make "self" (or whatever) a mandatory formal parameter in
> methods? Why not make "self" a predefined identifier within methods?

Coming from a C++ background, I used to wonder that too :-). It ends
up being *very* handy to be able to call the methods directly. By
directly, I mean with an explicit statement of the instance variable
as a member of the argument list. Looking at your sample code above,
I can:

temp = my_class
temp.f() # call method the standard way
my_class.f(temp) # call method explicitly
meth = my_class.f # remember unbound method
meth(temp) # call method explicitly
temp.meth # AttributeError meth: you had to call it the other way!

I think it ends up being much cleaner to not try to hide this implicit
instance (as C++ does). Invoking __init__() methods in base classes
(using the explicit call) was the first place I saw this formulation
working out well. When I started to play with pointers to methods and
pointers to function (I know, I'm revealing my underlying C background
in my terminology) this formulation of an arg list for methods and
obvious associated calling conventions really seemed to flow together
nicely. If you didn't like my "contrived" example above showing the
pointer to method "meth," you can consider how a qsort()
implementation can blindly be handed a comparison-method, so long as
the calling args for that method looked "reasonable" to qsort (i.e.,
it "looked like" a function that took two args, and returned a 0, 1,
or -1).

> 7) More about contexts: having to fully specify variable contexts
> really bugs me. The more Python I write, the more it bugs me.
> It is correlated. It is a trend. I am bugged. Because: I prefer
> a language that does the work for me. Why isn't there a predefined
> context search order?

I think you lost me here :-(.

> 8) Why can't the debugger (pdb) understand the syntax:
> break <class>.<method>
> Instead I have to type:
> break <class>.__dict__['<method>']

I don't know the answer, 'cause I use the way cool windowing debugger
that also comes in the "package." :-).

> 9) Why does "cl" (clear all breaks) bomb? (pdb)

see answer to 8. I apologize if I'm being too glib, and you really
can't run the wdb debugger. Here again, a person in a similar state
can be more helpful.

Jim

Jim Roskind
voice: 408.982.4469
fax: 408.986.1889
jar@infoseek.com