[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: "static" declaration
Jeremy Hylton writes:
> >>>>> "DW" == Dan Weinreb <dlw@smartleaf.com> writes:
> DW> there is no place I can look to find the answer to the
> DW> question "what are the instance variables of this class",
> DW> since any imperative method anywhere is free to just add a new
> DW> one at any time. So I am forced to trace through all the
> DW> imperative paths in order to be able to draw my nice little
> DW> notes in my notebook that say what the classes are and what
> DW> their instance variables are.
>
> I have been wondering, as this thread progresses, why do you want to
> have a notes that say what the instance variables of classes are? I
> don't mean to deride the need for these notes. Rather, I'm wondering:
> Why I haven't been bothered by the lack of declarations for instance
> variables in Python classes. Conversely, what about Perl makes the
> lack of declarations a nuisance?
Perl's philosophy is to have sensible defaults; consequently, if you
try to fetch a hash item (Perl calls associative arrays hashes) that
doesn't exist, it returns undef (Perl's equivalent to NULL.), and
undef acts like an empty string or 0 in string and numeric contexts.
(Although it gives you a warning.)
Python's philosophy is to refuse to guess in the face of ambiguity;
consequently, attempting to apply a string or numeric operation to
None (Python's NULL) raises an exception, and so does trying to
retrieve a dict item (Python calls associative arrays dicts) that
doesn't exist.
In both languages, instance variables are typically stored in an
associative array. So, in Perl, reading a nonexistent instance
variable gives you undef, while in Python, it raises an exception.
Since NULL is a sensible initial value for many instance variables,
Perl constructors don't need to mention those instance variables, but
Python __init__ functions (I can't call them constructors anymore,
dammit) often need to.
There are cases where one instance variable is only meaningful if
another one has a non-default value, and in those cases, it's safe to
leave them uninitialized in the constructor and then add them later.
For example, a UTF-8 decoder in C I was playing with the other day has
a "constructor" like this:
decoding_state *new_decoding_state() {
decoding_state *x = malloc(sizeof(*x));
if (x) {
x->len = 0;
x->ucs = 0xdeadbeef; /* undefined unless len != 0 */
x->min = 0xdeadbeef; /* likewise */
}
return x;
}
In this case, not setting the attributes in the constructor, and
getting an exception if they're accessed without setting len first ---
is preferable to setting them to some bogus value.
But the more usual case is that all instance variables are
well-defined at all times after __init__ has run.
> It seems that knowing the complete set of instance variables is, by
> itself, rather uninteresting.
But if that's what you want, perl -lne 'print $2 while
/\$(this|self)->\{(.*?)}/g' | sort -u does a pretty good job as long
as the code you're looking at follows normal Perl conventions (and
doesn't generate Perl modules).
With regard to Dan's original problem, by the way, I usually determine
whether a Perl function is intended to be a class method or an object
method by whether its first parameter is called "$class" or "$this" or
"$self"; it's slightly less visually clear than "static", and it's
only a convention, but it works pretty well most of the time.
I prefer that languages have facilities for expressing things like
this rather than having to fall back on convention.
> It's clear that eggs() is a method, because it is defined in a class.
> _state must be an instance variable since it's an attribute of state,
> while arg is a local variable. (It's also clear that eggs() isn't a
> static or class method, because those are defined differently.)
In old Python, it's even better: it's clear that eggs() isn't a static
or class method because no such thing exists. I think you're
overselling the new way of doing things, which is to put "eggs =
staticmethod(eggs)" somewhere after the end of the method definition
(conventionally, immediately after it).
--
<kragen@pobox.com> Kragen Sitaker <http://www.pobox.com/~kragen/>
Edsger Wybe Dijkstra died in August of 2002. This is a terrible loss after
which the world will never be the same.
http://www.xent.com/pipermail/fork/2002-August/013974.html