My proposal:
alias httpport : 80
alias astring : "Strings are ok too!"
alias alist : [a, b, c]
alias atuple : {one : 1} #etc.
alias aconstant : can be anything not containing an explict nl or #
alias true: 1 # create an alias for 1
alias true: not 0 # this is ok too, but not after the previous
# declaration!
>> error: redefinion error!
alias false: is zero # everything up to the nl or octothorpe is the
# replacement text
A reoccurance of the same label to the left of the colon in the same
scope (or should this be global?) is a redefintion error. The occurance
of a newline in the replacement text to the right of the colon is an
error _even_if_escaped_. Encoded newlines: "\n" are acceptable but are
not converted by the alias statement. In fact no processing at all of the
replacement text is ever done, although the resulting text may be
evaluated by the python parser.
There is no possiblity of substitution in these (what are essentially)
macros, nor should there ever be - this is not an analog for #define
foo(a,b,c) where one can expect a, b and c to be substituted within the
body of the define! The only purpose is to assign invariant labels to
constant values.
Of course, there might be other hidden gotchas that I haven't thougt
of...
Dave LeBlanc
Hm. Unconventional use of the colon, isn't it? (For Python, I mean.)
Anyway - what is it you want with this? Efficiency, on enforcing
the non-changing state of the variables?
I can't really see the need for this myself - but if something like it is
ever implemented, I really hope we won't have similar solutions to those
used to simulate private variables. I mean...
>>> _const_httpport = 80
>>> _const_httpport = 90
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ConstError: constant '_const_httpport' is already defined
<shudder>
> Dave LeBlanc
--
Magnus Lie Hetland http://www.hetland.org
"Reality is that which, when you stop believing in
it, doesn't go away." -- Philip K. Dick
I was just thinking that a class instance that overrides __setattr__
can provide the same thing. I suppose use keyword arguments to
__init__ to provide the values, and all future assignments blow up.
-D
Extremly ugly and I don't know what the real benefits are...
syntactic sugar.
Andreas
It's pretty easy to ensure that an exception is raised when an
attribute of a given module is re-bound -- all it takes is for
that module to NOT be a module, but rather an instance.
Put in const.py...:
:: start
class ConstError(TypeError):
pass
class _const:
def __setattr__(self,name,value):
if self.__dict__.has_key(name):
raise ConstError, "Can't rebind const(%s)"%name
self.__dict__[name]=value
import sys
sys.modules[__name__]=_const()
sys.modules[__name__].ConstError = ConstError
:: finis
That's it. Now any module can:
import const
and names can be bound ONCE in const:
const.magic = 23
but NOT twice:
const.magic = 42 # raises a const.ConstError
This doesn't give you an 'alias' that's actually an arbitrary
string of code, and as written still lets you explicitly
del const.magic
const.magic = 88
though it would suffice to add __delattr__ to impede
that, of course. But I think it's sufficient, anyway.
Hmmm, maybe I should add that to the Cookbook... it
seems a little-known technique. I think it only works in
Python 2.1, btw. [Done -- not approved yet, but it's at
http://aspn.activestate.com/ASPN/Python/Cookbook/Recipe/65207
and I think it's already generally-visible].
Alex
David> alias httpport : 80
...
Interesting idea. Why do you prefer ":" over "="?
--
Skip Montanaro (sk...@pobox.com)
(847)971-7098
I don't see the problem with the colon - after all, isn't that the syntax
for
a key: value pair that will go into the dictionary? I'd just as soon have it
called "const" rather than "alias", though.
> Anyway - what is it you want with this?
The reasons I want it are very simple:
1. it avoids coding errors when you have to have the same string
constant in the code in multiple places. It's a lot easier for the
compiler to complain about an uninitialized variable than to check
lots of code with Eyeball Mark I.
2. Sometimes the "magic number" just isn't really very descriptive.
Picking good names for things is part of what makes your module
understandable six months from now.
>Efficiency, on enforcing
> the non-changing state of the variables?
If I call something "const", then I want it to be CONSTANT, not
something that can be changed at the whim of a coding mistake, or a
misguided "cute hack."
..but what is your opinion as to whether this functionality belongs in the
language itself?
Those coming from other languages are likely to expect to have constant
values of some sort.
Your solution looks great, but still you have to type "const.foo" instead of
just "foo".
How much run-time overhead does this involve? I suppose only a tiny amount,
and perhaps no more than even a 'language-level' implementation would have,
but I think I would probably not use this in my most-inner loops.
I suppose one could always bind a local name to the value..
width = const.width
..but then 'width' is no longer constant, and can be changed at will.
def fn(a,b,c):
if something:
for thing in things:
etc.
(in fact it occurs to me that at least the def statement is a form of
alias where (argument) substition is done! At least conceptually the body
of a function replaces it at invocation time.)
Creating an inherent means of creating constants (or my preferred
aliases) is good computer science as someone else mentioned in a reply
post. Magic numbers are bad - they're sloppy programming and a source of
errors if they must be used in several places etc. OTOH, aliases clarify
program meaning and imho make things more comprensible to newbies. I
think all would agree that "if something is true:" is clearer then "if
something is not 0:". Likewise, "userpermissions" is much more meaningful
then 0677 (or whatever - it's been too long since i've used unix heavily,
but I think the point is clear).
As for the distinction between const(ant) and alias: Perhaps it's a
matter of aesthetics, but somehow alias is more descriptive then const
since it suggests the substition that's happening. Further, it's
incorrect to call "alias true: not 0" a constant imho. To further
belabour (with a tip of the hat to the english cousins) the point, it
read so nicely to be able to say "if something is true" rather then "if
something is not 0" (saves on typing too :-)).
Other suggestions to import large libraries or make modules instances are
not things calculated to gladden the heart of a newbie who seeks
simplicity, nor would the code enlargement (my aren't I diplomatic ;))
win the approval of an experienced developer who doesn't want to search
exteraneous lines when a bug pops up - which is statistically more likely
with more lines of code, not to mention the antics needed to do something
that should be as simple as possible (imho).
One can certainly argue that this is syntactical sugar. It does however
serve a multitude of good purposes among which are: maintainability;
clarity; consistancy; correctness; good programming habbits; - a not
inconsiderable set of advantages for a little sugar.
Finally, this wouldn't break any code, nor would anything (excepting
perhaps peer pressure) force anyone to use it.
Sincerely,
Dave LeBlanc
> alias true: 1
...
>...read so nicely to be able to say "if something is true"
it's even easier than that:
if something:
...
..which can 'read' just as well, if you choose your names accordingly.
..but on a more general note, am i to understand that you are suggesting
C-style macros, where code is 'physically substituted', before being run?
That would be a Bad Thing, i think. C was a nice little language before it
turned into a giant mess of macro substitutions.
'def', while not an assignment per se, has the same semantics as assignment,
i.e. a name bound with 'def' can be rebound with assignment and vice versa.
The following two statements are basically identical:
def f(x): return x
f = lambda x: x
I consider this a wart in the language. Binding a function to a name is
logically and physically the same operation as binding any other value to a
name; it should therefore use the same syntax.
--
Rainer Deyke (ro...@rainerdeyke.com)
Shareware computer games - http://rainerdeyke.com
"In ihren Reihen zu stehen heisst unter Feinden zu kaempfen" - Abigor
They're close, with one obvious difference:
D:\py21>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
Alternative ReadLine 1.4 -- Copyright 2001, Chris Gonnerman
>>> def f(x): return x
...
>>> f.__name__
'f'
>>> f = lambda x: x
>>> f.__name__
'<lambda>'
>>>
> I consider this a wart in the language. Binding a function to a name is
> logically and physically the same operation as binding any other value to
a
> name; it should therefore use the same syntax.
You consider it a wart that more than one statement can bind
variables? It's not just assignment and def -- class, import
and from behave the same way. Notice one pattern: all kinds
of non-assignment binding-statements deal with objects whose
*NAMES* are significant *BOTH* in deciding the variable-name
to bind *AND* to locating or initializing the object that is
being bound. The f.__name__ issue above is not a "it just
so happens". It's similar to, say:
import mynicemodule
vs
mynicemodule = __import__('mynicemodule')
Thanks to import, def, and class, I do not need to type a LOT
of names twice, in the _extremely_ common case in which I do
want the variablename being bound to be the same as the name
of the object that is being bound (which is normally also the
object that is contextually being *created*, although the
semantics of sys.modules make creation a once-only occurrence
for module-objects specifically).
If _only_ assignment could ever possibly bind a variable, we
would need *expressions* (similar to today's __import__, but
syntactically much more complicated, since needing to hold
arbitrary amounts of code) that would also require us to type
each name twice -- or they would have to use black magic to
learn the name they're being bound to.
Moreover, we'd then have to deal with that precious built-in
function, setattr. Binding a value to a named attribute is
logically and physically the same operation as binding that
value to that same named attribute (since it's EXACTLY the
same operation...); by your logic, "it should therefore use
the same syntax". So how comes:
fee.fie = foo.fum
and
setattr(fee, 'fie', foo.fum)
and
fee.fie = getattr(foo, 'fum')
and
setattr(fee, 'fie', getattr(foo, 'fum'))
use four widely divergent syntax forms for the same op?-)
(operator.setitem has obvious similarities, too).
The answer, from my POV, is that names are reasonably-serious
matters. In the case of attribute-reference-syntax versus
setattr/getattr, the reason for the difference is that the
attribute reference is the obviously right way to do it for
an attribute name that is an overt constant, the built-in
function is just as obviously right when the attribute name
is anything *BUT* an overt constant (in identifier-syntax).
In the case of import, the specific advantage of the statement
is avoiding having to type the same name twice in 99.44% of
cases. In the case of def and class, I have that same
advantage, plus, no need for any syntax which lets an
expression contain and coordinate statements.
Practicality beats purity, and this set of language design
choices strikes me as something that Python got just right.
A pretty deep, widespread, and precious "something", too.
Alex
Fortunately ***NOT***!!! Such a horrible "conceptual"
choice for a function-execution model would put pay to
any chance of *RECURSION*.
> read so nicely to be able to say "if something is true" rather then "if
> something is not 0" (saves on typing too :-)).
Such "read so nicely" tests would of course not work as
expected (with or without alias). The object None, for
example, evaluates as false, but if you test its identity
with 0, you will of course find they're not *identical*
(how COULD they be -- they're different in every respect,
the ONLY thing they have in common is evaluating as false!).
It seems to me that the LAST thing we need is encouraging
"read so nicely" forms that do NOT do what a naive newbie
might expect. It is absolutely fundamental that the
newbie learns to write his/her logical tests as:
if something:
...
and
if not something:
...
and *NOT*
if something is 1:
...
or
if something is 0:
...
or any "aliases" of these flawed forms.
> Other suggestions to import large libraries or make modules instances are
> not things calculated to gladden the heart of a newbie who seeks
> simplicity,
The module-instance (the const.py example I gave) would of course
be made by a NON-newbie, the newbie would just USE it. Why would
"a newbie who seeks simplicity" consider:
const.magic = 23
less simple than
alias magic : 23
?!?! The former uses exactly the same syntax as any other binding,
requiring the newbie to learn absolutely no new syntax. The latter
requires the newbie to learn one more "simple keyword-statement", with
a syntax totally different from that of all OTHER simple keyword
statements. It seems to me that your claim that all of the extra
conceptual and syntactical baggage FAVOURS simplicity, when common
sense suggests extra baggage REDUCES simplicity, is an extraordinary
claim, and thereby requires extraordinary proof.
> nor would the code enlargement (my aren't I diplomatic ;))
> win the approval of an experienced developer who doesn't want to search
> exteraneous lines when a bug pops up - which is statistically more likely
What "code enlargement" are you talking about? Which "exteraneous" (?)
lines? In a script using "module const" there may or may not be a
single line
import const
for explicitness (the alternative is having it performed implicitly
at startup, e.g. by sitecustomize.py &c &c, placing const in the
__builtin__ module, of course). That's up to the "experienced
developer" who decides constants are necessary at his/her site.
> with more lines of code, not to mention the antics needed to do something
> that should be as simple as possible (imho).
What "antics"? If you want 'const' to be activated by default
in every Python installation (e.g. in site.py), write a PEP
proposing just that. You DO realize, of course, that no matter
what little chance such a PEP may have, it IS going to be at
least a thousand times more likely to be adopted than anything
that will introduce a new keyword and thereby break perfectly
working code -- that's something that can *possibly* happen
only for really momentous developments (such as the new proposed
"yield" keyword-statement for generators) which DESPERATELY NEED
a new statement (can't POSSIBLY work halfway-decently without).
> One can certainly argue that this is syntactical sugar. It does however
> serve a multitude of good purposes among which are: maintainability;
> clarity; consistancy; correctness; good programming habbits; - a not
> inconsiderable set of advantages for a little sugar.
I fail to see ANY of these advantages when comparing your "alias"
with a "const" module installed by site.py. How is
alias magic : 23
more maintainable, clearer, more consistent, more correct, or
a better programming habit than
const.magic = 23
?!?! Please bring SOME kind of argument for such extraordinary
assertions... your bald statements are not "support" for them!
> Finally, this wouldn't break any code,
Puh-LEEZE. *ANY* use of 'alias' in existing code would be
broken. Let's not make such obviously-false assertions...
Alex
Thanks!
> ..but what is your opinion as to whether this functionality belongs in the
> language itself?
Neutral. I don't think it would do Python any irreparable harm if the
standard site.py included 6 more lines to install a suitable instance
in sys.module['const'], but it's hardly a key issue IMHO.
> Those coming from other languages are likely to expect to have constant
> values of some sort.
Those coming from other languages expect all sort of things which
their previous languages "offered" to them. Implicit scoping in
methods (rather than explicit self.whatever references), magical
calling of superclasses' __init__/__del__ (if from C++ -- not if
from Java), ability to call functions without parenthesis (if from
Visual Basic up to 6 included -- removed in VB 7), implicit change
of strings to numbers and back (if from Perl or Visual Basic, not
if from C++ or Java), mandatory and/or optional declarations of
variables and/of their types, class methods (with very different
semantic expectations if they come from Smalltalk or rather from
C++ or Java), macros (again, very different expectations if from
C, or Scheme, or Common Lisp), "reference" parameters (implicitly,
if from Fortran or some versions of VB -- at least as an option,
if from C++ or other versions of VB or Pascal), private and/or
'friendly' and/or protected members (if from C++ or Java or Eiffel,
at least), a baseclass common to all objects (if from Java or
Smalltalk, not if from C++), unnamed codeblocks (if from Smalltalk
or Ruby), named break/continue (if from Java or Perl)...
Oh, and, last but not least -- braces and/or begin/end, OF COURSE!-)
I COULD go on writing for hours and hours, of course, just in
listing all the things that those coming from other languages
are "likely to expect". If Python had 1/10th of such variously
"expected" features, it would be a bloated, unwieldly, unusable
monster. Of course, every paladin of one such change resolutely
refuses to look at the overall picture -- *HIS* change (or, in
theory, "hers" -- but I have not witnessed female proponents of
such changes, yet:-) is the one that matters. "Yeah, right".
Guido has proved for over a decade that he does an insanely
great job in triage of such risk-of-featuritis, so most sensible
people have long given up on the Sysiphean task of explaining
to the endless stream of change-proponents how and why their
desires can already be well met in Python, or how and why they
are best left unmet.
Those which CAN be well met (a large majority) often involve
some tiny device -- a few lines' worth of class or function --
and it is hopefully well known that any site can easily decide
to make such things "built-in" by tiny mods to site.py (or,
better, siteconfigure.py), while of course packages that are
to be distributed which rely on such devices can in turn
distribute the devices themselves as well.
Only an EXTREME minority of such features could or should be
mandated as built-in for ALL sites forever -- else, Python
would again bloat, albeit not strictly speaking on the
language-side of things. Special syntax-sugar (which is
an extremely frequent request) for any such feature is, of
course, MOST unlikely to get into the language -- thanks be.
Any syntax sugar whatsoever for const.goo would be a total,
utter, unrelieved, unPythonic horror, IMHO.
Having 'const' bundled in the default site.py would be no
horror. Probably not the wisest single thing to add out
of all the huge list above (which is only a little and very
partial list of typical desiderata stemming from other
languages), but not the least-wise one either.
One (IMHO) Python enhancement would be to give dictionaries
some finer-grained control on their degree of mutability.
The ability to selectively make SOME existing keys non
rebindable and/or non removable _would_ come in handy in
quite a few places ('constants' included), as would the
related ones of locking a dictionary against addition of
new keys. Since ALMOST all Python namespaces are in fact
dictionaries (local-variables of functions being the
signal exception), such locking would give the basic
semantics for several desirable tricks. But that's a
whole 'nother issue, would offer no new "pretty" syntax
sugar anyway, and thus would most likely be of no
interest whatsoever to most typical change-proponents.
> Your solution looks great, but still you have to type "const.foo" instead
of
> just "foo".
Right! That's what makes it *Pythonic*. No messing about
with the semantics of identifiers.
> How much run-time overhead does this involve? I suppose only a tiny
amount,
> and perhaps no more than even a 'language-level' implementation would
have,
> but I think I would probably not use this in my most-inner loops.
If your innermost loops are in functions, copying whatever
values you're using in the depth of the loop to local
variables of your functions IS likely to offer you a
pretty good speedup. This includes functions you are
calling, by the way, as well as methods you're calling, &c.
But -- don't optimize prematurely... it's a losing approach!
> I suppose one could always bind a local name to the value..
> width = const.width
> ..but then 'width' is no longer constant, and can be changed at will.
Local variable 'width' never was constant, so 'no longer' is
a strange word-choice (it seems to imply that once upon a
time it was?-).
But if you're talking of an inner-loop, you're talking of a
few lines of code, so where's the risk?
Alex
<snip>
> value to that same named attribute (since it's EXACTLY the
> same operation...); by your logic, "it should therefore use
> the same syntax". So how comes:
> fee.fie = foo.fum
> and
> setattr(fee, 'fie', foo.fum)
> and
> fee.fie = getattr(foo, 'fum')
> and
> setattr(fee, 'fie', getattr(foo, 'fum'))
> use four widely divergent syntax forms for the same op?-)
Well, really eight if you note that fum requires arguments: ;-)
fee.fie = foo.fum(eggs.spam)
But could you explain why I see this as two forms but you see it as four?
Is it a left/right thing?
--
Emile van Sebille
em...@fenx.com
---------
I didn't understand David's proposal as macro preprocessing. I understood it
as a request for a one-time assignment (i.e., one that guaranteed that the
name
couldn't be reassigned (or rebound to a different object, for language
purists)).
As far as I'm concerned, that's the essence of the proposal: whatever object
is
bound to the name will not change (at least, until the code is edited!) This
means
that it really only makes sense for immutable objects.
I also don't really care about the syntax - there are people working on
Python
who are much more knowledagable about what would fit cleanly. I prefer
"const",
but I could live quite happily with "alias." Likewise, I prefer "=", since
my
vision is that it really is a (one-time) assignment, but I could live with
":".
The run-time issue (how to make it happen) could be fairly messy - I don't
know
of any mechanism currently in Python that will prevent a name from being
rebound
to another object.
The problems with the C language #define statement are outside of the
scope of this discussion, other than as a horrible example of how to add a
layer
of obfustication to a program.
John Roth
>
>
>
>
I'm quite aware of that, hence my use of the name 'basically'. In most
cases, '__name__' isn't important. In the case of functions, it is almost
exclusively used for tracebacks. If the traceback instead printed the line
of code from which the function was called, the user would almost always
have the same information, so '__name__' becomes redundant.
> You consider it a wart that more than one statement can bind
> variables? It's not just assignment and def -- class, import
> and from behave the same way. Notice one pattern: all kinds
> of non-assignment binding-statements deal with objects whose
> *NAMES* are significant *BOTH* in deciding the variable-name
> to bind *AND* to locating or initializing the object that is
> being bound. The f.__name__ issue above is not a "it just
> so happens". It's similar to, say:
> import mynicemodule
> vs
> mynicemodule = __import__('mynicemodule')
This is similar to what you have to do if you want a named object that is
not a class, function, or module:
class NamedObject:
def __init__(self, name): self.name = name
spam = NamedObject('spam')
If classes, functions, and modules require syntax sugar to prevent typing
the same thing twice, I see no reason why this syntax sugar cannot be
generic enough that it can do the same thing for 'NamedObject' above.
__setattr__ of course. It only works for an instance, but that
just means the 'module' called const (or alias, or whatever) has
to be an instance -- easy, as I already showed. If as you say
you're not hung on the syntax, either const.name or alias.name
CAN easily be made unrebindable after an 'import const' or
'import alias'. Again, see my post of yesterday on this thread.
Alex
Surely a newbie can understand that if you assign a variable to a
value, and then never change it, then it is working as a constant.
I have no problem having cxonstants like this, e.g.
programVersion = "0.2.7"
it seems to me that:
alias programVersion: "0.2.7"
is no clearer, and is an extra something for a learner to have to learn.
Entities should not be multiplied unnecessarily!
> I
>think all would agree that "if something is true:" is clearer then "if
>something is not 0:".
What's wrong with:
if something:
which is what I would use here.
> Likewise, "userpermissions" is much more meaningful
>then 0677
Indeed so. And in python, one can say:
userPermissions = 0677
(Personally I prefer the way Smalltalk handles non-decimal radixes,
i.e. 8r677)
>One can certainly argue that this is syntactical sugar. It does however
>serve a multitude of good purposes among which are: maintainability;
>clarity; consistancy; correctness; good programming habbits;
When I hear that phrase, I reach for my gun. Go and use Pascal or
Eiffel if you're into bondage-and-discipline.
--
## Philip Hunt ##
## ph...@comuno.freeserve.co.uk ##
you mistake a simple example for how something would of necessity be
done. it could just as esasily be "alias true : not none and not 0"
Of course you would prefer your method...
Ok, so it _might_ break some existing code... so might using const or
magic or many other words.. such logic suggests that since cobol was
(probably) the first "high level" language that we should all still be
using it since to change or add anything might break older stuff.. yeah,
a somewhat contrived example, but i'm sure you get the idea... maybe
staying with python 1.3 vs 2.1 would be a better example.
Dave LeBlanc
<snip excellent comments re: 'constants'>
> ...
> One (IMHO) Python enhancement would be to give dictionaries
> some finer-grained control on their degree of mutability.
> The ability to selectively make SOME existing keys non
> rebindable and/or non removable _would_ come in handy in
> quite a few places ('constants' included), as would the
> related ones of locking a dictionary against addition of
> new keys. Since ALMOST all Python namespaces are in fact
> dictionaries (local-variables of functions being the
> signal exception), such locking would give the basic
> semantics for several desirable tricks.
> ...
now, that's an interesting idea.
how would that look, syntactically?
dict['A']=1
dict.lock('A')
..making the value unchangeable?
..and would attempts to set the value raise an exception?
> you mistake a simple example for how something would of necessity be
> done. it could just as esasily be "alias true : not none and not 0"
So what would the semantics of 'a == true' be? There are two option, both
wrong (and I won't even mention the infinite number of other objects that
test as 'false').
>>> true = not None and not 0
>>> 5 is true
0
>>> 5 is not None and not 0
1
>>> 0 is not None and not 0
1
I absolutely agree that entities shouldn't be multiplied unnecessisarily!
However your suggestion in fact does just that: there is nothing that
prevents one from reassigning to programVersion in some module you
import. Oops... The important difference is that you can't change the
replacement text of an alias once set: it's immutable.
> > I
> >think all would agree that "if something is true:" is clearer then "if
> >something is not 0:".
>
> What's wrong with:
>
> if something:
>
> which is what I would use here.
Hardly worth mentioning that if (something) is a common source of error
in languages like C and C++ where the missing boolean is assumed.
> > Likewise, "userpermissions" is much more meaningful
> >then 0677
>
> Indeed so. And in python, one can say:
>
> userPermissions = 0677
And in Python, 432 lines later one can say userPermission = 0777 and then
scratch one's head as to why file permissions have gone awry. If it where
an alias, you'd get a usefull error: Error: attempt to change alias.
> (Personally I prefer the way Smalltalk handles non-decimal radixes,
> i.e. 8r677)
That I can agree with :>
> >One can certainly argue that this is syntactical sugar. It does however
> >serve a multitude of good purposes among which are: maintainability;
> >clarity; consistancy; correctness; good programming habbits;
>
> When I hear that phrase, I reach for my gun. Go and use Pascal or
> Eiffel if you're into bondage-and-discipline.
Oh god am I tempted... but i'll refrain.
Dave LeBlanc
Speaking of aliasing... I fondly recall Occam's method of aliasing. With
Occam, one can alias array slices so that working with message packets is
extremely easy.
For instance, one can alias (e.g. "lastName") a slice [16:32] of an Occam
array of bytes "byteArray" with:
lastName IS [byteArray FROM 16 FOR 16]:
and then use lastName as a new array name. Then the first byte can be
referrenced with:
lastName[0] := 'a'
This, of course, will change the 17th byte in byteArray to 'a'.
Multidimensional arrays can be sliced and aliased, also -- very convenient,
efficient, and clear.
Aliasing could significantly improve the efficiency of a program running on
the Inmos Transputer, as its instruction set favored small index offsets,
and the aliasing lets the compiler know how to do that.
This would be nice on Python as well, particularly since naming a list slice
actually creates a copy (perhaps I've missed some capability here).
Thanks for your response!
In article <9gclv...@enews1.newsguy.com>, ale...@yahoo.com says...
> "David LeBlanc" <whi...@oz.nospamnet> wrote in message
> news:9gbsdv$8ft$9...@216.39.170.247...
> ...
> > alias where (argument) substition is done! At least conceptually the body
> > of a function replaces it at invocation time.)
>
> Fortunately ***NOT***!!! Such a horrible "conceptual"
> choice for a function-execution model would put pay to
> any chance of *RECURSION*.
Actually so, in fact some languages do just that as a performance
enhancer, but not worth arguing - nor does it address the original point.
Arguing against an aside isn't useful. BTW, i'm not english, but I
believe the expression is "put paid to". I think it came from the days of
wooden ships when seams in the hull where "paid" (stuffed) with oakum and
tar. Hmmm.. maybe that's where the expression "get stuffed" came from but
I digress ;-) (NOT meant personally <g>.)
> > read so nicely to be able to say "if something is true" rather then "if
> > something is not 0" (saves on typing too :-)).
>
> Such "read so nicely" tests would of course not work as
> expected (with or without alias). The object None, for
> example, evaluates as false, but if you test its identity
> with 0, you will of course find they're not *identical*
> (how COULD they be -- they're different in every respect,
> the ONLY thing they have in common is evaluating as false!).
Introducing alias does not introduce immunity to incorrect programming.
It does make easier to correct one line that's substituted 1,000 times
then it is to substitute all 1,000 lines you did in error.
> It seems to me that the LAST thing we need is encouraging
> "read so nicely" forms that do NOT do what a naive newbie
> might expect. It is absolutely fundamental that the
> newbie learns to write his/her logical tests as:
> if something:
> ...
> and
> if not something:
> ...
> and *NOT*
> if something is 1:
> ...
> or
> if something is 0:
> ...
> or any "aliases" of these flawed forms.
If "naive newbie" makes a programming error he/she is going to make a
programming error whether or not alias is present. This helps, it does
not guarantee that you won't make mistakes.
> > Other suggestions to import large libraries or make modules instances are
> > not things calculated to gladden the heart of a newbie who seeks
> > simplicity,
>
> The module-instance (the const.py example I gave) would of course
> be made by a NON-newbie, the newbie would just USE it. Why would
> "a newbie who seeks simplicity" consider:
>
> const.magic = 23
>
> less simple than
>
> alias magic : 23
It's not less simple - nor is it more complex. Your forgot the "import
const" bit needed for your part unless one does what you suggest and
manually add it to the default libraries (which then is loaded by every
program - I don't know if Python does "lazy loading", so this might not
be a valid arguement). What fun for a newbie!
The thing that an alias does address that your method does not is that if
the newbie does "const.magic = 23" and then he/she imports some nice
module, he/she is not going to be confused by the imported module's
changing the value of magic...
> ?!?! The former uses exactly the same syntax as any other binding,
> requiring the newbie to learn absolutely no new syntax. The latter
> requires the newbie to learn one more "simple keyword-statement", with
> a syntax totally different from that of all OTHER simple keyword
> statements. It seems to me that your claim that all of the extra
> conceptual and syntactical baggage FAVOURS simplicity, when common
> sense suggests extra baggage REDUCES simplicity, is an extraordinary
> claim, and thereby requires extraordinary proof.
What "simple keword" syntax are you referring to? It does follow the idea
of key : value in dictionaries and that many other statements have one
part separated from another by a colon.
> > nor would the code enlargement (my aren't I diplomatic ;))
> > win the approval of an experienced developer who doesn't want to search
> > exteraneous lines when a bug pops up - which is statistically more likely
>
> What "code enlargement" are you talking about? Which "exteraneous" (?)
> lines? In a script using "module const" there may or may not be a
> single line
> import const
> for explicitness (the alternative is having it performed implicitly
> at startup, e.g. by sitecustomize.py &c &c, placing const in the
> __builtin__ module, of course). That's up to the "experienced
> developer" who decides constants are necessary at his/her site.
Heaven forefend the newbie using what is generally considered good
programming experience from the start. Let them develop the bad habbit of
using magic numbers and other obscurities and then, once the bad habbit
is ingrained, introduce the idea of consts with meaningful names... Wow,
wish i'd thought of that!. Maybe it was my mistake, but I was under the
impression that one of Python's objectives was to be a teaching language.
Better to teach good practice from the start isn't it?
(Sorry, the word is "extraneous" - i'm a prgammer not a dictionary :). I
actually do spend considerable time on longer posts proofing.)
> > with more lines of code, not to mention the antics needed to do something
> > that should be as simple as possible (imho).
>
> What "antics"? If you want 'const' to be activated by default
> in every Python installation (e.g. in site.py), write a PEP
> proposing just that. You DO realize, of course, that no matter
> what little chance such a PEP may have, it IS going to be at
> least a thousand times more likely to be adopted than anything
> that will introduce a new keyword and thereby break perfectly
> working code -- that's something that can *possibly* happen
> only for really momentous developments (such as the new proposed
> "yield" keyword-statement for generators) which DESPERATELY NEED
> a new statement (can't POSSIBLY work halfway-decently without).
Why? Is there something you know about how well new ideas are viewed by
the core python team that I don't? I guess we'll never see the
introduction of another Python keyword like... hmm... "do" since it might
break perfectly working code? I'd be clever here and point out in Latin
that languages that don't grow die... but I don't know Latin since it's
dead!
Frankly, while it might not be as DRAMATIC as GENERATORS, in it's own
quiet way, *I* think it's just as momentuous. (As for "yield" - whatever
does a generator need yield for? My understanding of generators is that
they produce a new value based on retained state, not actually generate a
huge sequence - oops, there I go digressing again.)
I don't see this as anything as earthshaking as introducing nested scope
which is going to cause far more problems in changing program structure
(when it becomes the default) then changing the name of an identifier.
Nor do I think that this is the first new keyword that was introduced
since the inception of Python - of course, not having done the research
to find 1.3 or earlier if they're publically available, I won't make such
a bald statement.
> > One can certainly argue that this is syntactical sugar. It does however
> > serve a multitude of good purposes among which are: maintainability;
> > clarity; consistancy; correctness; good programming habbits; - a not
> > inconsiderable set of advantages for a little sugar.
>
> I fail to see ANY of these advantages when comparing your "alias"
> with a "const" module installed by site.py. How is
> alias magic : 23
> more maintainable, clearer, more consistent, more correct, or
> a better programming habit than
> const.magic = 23
> ?!?! Please bring SOME kind of argument for such extraordinary
> assertions... your bald statements are not "support" for them!
I suggest you read an introductory book on good programming practice. If
you fail to see any of these advantages, then I shudder to think about
your code quality. Seriously, please bring SOME kind of argument for
saying that such notions are NOT a better programming habbit then... etc.
How is your suggestion that a new user:
1. Figure out how to import a feature that's inherantly available
in many other programming languages.
2. Make sure to not ever change any variable meant to be constant.
3. Figure out why the program won't work when const.magic magically
changes because they imported a module that changed it without notice or
warning.
4. How are you going to ensure that developers are going to
indentify every "meant to be constant so don't use this identifier as a
constant" constant that they create? Heck, you can't even get programmers
to do comments reliably and that's built in now! Forstalling the obvious
argument, of course there is nothing that ensures that any developer is
going to practice safe programming and use an alias... this isn't meant
to legislate against stupidity (who was that king that decreed that the
tide not come in?) but rather to facilitate doing things more correctly.
any better then what i've proposed?
> > Finally, this wouldn't break any code,
>
> Puh-LEEZE. *ANY* use of 'alias' in existing code would be
> broken. Let's not make such obviously-false assertions...
Yeah, that was my error - of course anyone can use "alias" as an
identifier. I refer you to my previous remarks with respect to changes in
Python since the first version, above. At least, unlike the recent furor
over changing the semantics of "print", this is new.
> Alex
Fred
P.S If you're confused by "Fred", I changed my identifier - oops, did I
forget to mention that in the docs?
Dave LeBlanc
My last words on this thread -- I hope. I've got a trip coming and too
many things to do in the too-short time before I leave, to waste more
hours flaming back and forth. If you need to make sure I see some
specific question, observation or whatever, pls cc me, as I may skip
any future posts in this thread.
> > if something:
> > ...
> > and
> > if not something:
> > ...
> > and *NOT*
> > if something is 1:
> > ...
> > or
> > if something is 0:
> > ...
> > or any "aliases" of these flawed forms.
>
> If "naive newbie" makes a programming error he/she is going to make a
> programming error whether or not alias is present. This helps, it does
> not guarantee that you won't make mistakes.
In fact, one alias example you gave specifically ENCOURAGES this
likely beginner-without-C/C++-background mistake, by, as you said,
offering a seductively nice "is false"/"is true" anti-idiom (my coinage,
but similar to the use of "anti-pattern" to describe a recurring way
to design or code that damages program qualities or productivity).
Encouraging beginners to err does make it more likely they'll err.
> > "a newbie who seeks simplicity" consider:
> >
> > const.magic = 23
> >
> > less simple than
> >
> > alias magic : 23
>
> It's not less simple - nor is it more complex.
It's more complex because there is a new keyword "alias"
whose syntax is different from all others. The colon in a
dictionary display takes an EXPRESSION on either side,
this one would take an expression on the right and an
IDENTIFIER on the left -- a terribly subtle distintion to
impart to a beginner. The former usage relies on the
assignment-syntax which any beginner learns rapidly,
and makes absolutely no specialcase to be learned in ANY
sense, neither syntactically nor semantically.
Having less to learn is simpler.
> Your forgot the "import
> const" bit needed for your part unless one does what you suggest and
> manually add it to the default libraries (which then is loaded by every
> program - I don't know if Python does "lazy loading", so this might not
> be a valid arguement). What fun for a newbie!
import is 'lazy' per-module but not per-run (it does do a tiny amount
of work the FIRST time it's executed in a program's run). But Python
does require import for extremely basic tasks such as accessing the
program's arguments or explicitly exiting from the program: in either
case one first does "import sys", before accessing sys.argv or calling
sys.exit. Therefore, a beginner WILL already know that, before just
about *ANY* foo.bar is used, one does "import foo" -- nothing new to
learn. So, if const were to be explicitly imported (probably wisest),
it would not add to Python's complexity in the least.
> The thing that an alias does address that your method does not is that if
> the newbie does "const.magic = 23" and then he/she imports some nice
> module, he/she is not going to be confused by the imported module's
> changing the value of magic...
sys.modules['const'].magic, in "my method", lets itself be bound ONCE
(globally). Therefore your claim in this paragraph is counter-factual. If
anything, you might critique the global nature of constants (although you
had hypothesized it as a possible enhancement, I believe).
> What "simple keword" syntax are you referring to? It does follow the idea
> of key : value in dictionaries and that many other statements have one
> part separated from another by a colon.
All compound statements in Python have uniform syntax:
<keyword> [other optional stuff] : # leading clause
<suite>
[maybe other clauses of similar form]
and 'alias' doesn't match this -- so it's not a compound statement and
has no business whatsoever with the way a compound statement uses
its colon[s]. Non-compound statements are called simple statements,
and except for assignment they're all uniform in syntax:
<keyword> [other optional stuff *WITHOUT* magic colons]
The dictionary-display form, the other use of colon in Python apart from
compound statements, has the following characteristics:
it is used within braces { }
it is TOTALLY INDEPENDENT of what kind of statement it
appears in -- it's an EXPRESSION
on both sides of the colon you have EXPRESSIONS (so, if
either is an identifier, it stands for whatever is already
bound to that identifier, NOT "for itself"!!!)
Your desired use of colon satisfies NOT EVEN ONE of these three rules.
Its VAGUE SIMILARITY to an existing form accompanied with crucial
semantic distinctions becomes therefore a serious hindrance. The
fact that the issue has subtlety makes it even worse. Syntax sugar
is much like government: it can't really do all that much good when
it's good, but it sure CAN easily do HUGE harm when it's bad. It's
hard to conceive of worse syntax sugar than one ACTIVELY MISLEADING,
similar but NOT equal to other spots in the language.
See for yourself:
foo = 1
bar = 2
foo = bar
this is an assignment: the LEFT-HAND identifier "STANDS FOR ITSELF"
and gets bound or (as in this case) rebound, without *ANY EFFECT AT
ALL* on whatever (if anything) it was previously bound to (except of
course that an object becomes eligible for recycling when all references
to it disappear). The '=' separator says exactly this: "my LHS identifier
is NOT being used as an expression". The RIGHT-HAND identifier, otoh,
IS being used as an expression -- it matters not a whit what the
identifier itself is, it DOES matter (it's the *only* thing that matters)
what OBJECT it is bound to. The other (non-assignment) case in
which '=' signals the same thing: keyword-style (named-style) for
parameters to a function. Again the LHS identifier STANDS FOR ITSELF
(it gets bound *in the namespace of the CALLED function*).
Vs:
xx={foo:bar}
BOTH identifiers here are used as expressions. They are not and can
NEVER be rebound by such usage.
You're proposing to use a colon *EXACTLY* like an equals-character
is always uniformly used in Python: to have its LHS identifier stand
for itself (and be bound or rebound) WITHOUT reference to or effect
on on whatever (if any) it was previously bound to.
Now try to write a couple of paragraphs explaining this anomaly, as
we would have to explain it to all Python newbies forevermore. "All
cases where an LHS identifier stands for itself are denoted with an
'=' separator *EXCEPT*... the colon always terminates the leading
clause of a compound statement, *EXCEPT*... the x:y form is an
expression when used in dictionary display, and in that case it of
course follows ordinary expression rules (each subexpression is
evaluated), *BUT* in the magical alias statement x:y is not an
expression and follows completely different rules, to wit... all statements
except assignment begin with a reserved keyword and are either
simple keyword statements, or compound statements, OR alias
which is completely and utterly different from ALL other statements
because...". Ohmygod. I have a hard enough time explaining the
*PERFECTLY SIMPLE, REGULAR AND SENSIBLE* underlying rules of
Python syntax and semantics, in ways that are (all at once:-) full,
precise, readable, concise, and memorable -- even a TINY durned
irregularity such as the use of parentheses in 'class' vs 'def' when
no bases (resp formal arguments) are present already rankles (let's
not get into "print>>", *PLEASE*)... your "alias" would throw a huge
spanner into the works.
"nor is it more complex" *INDEED*...!!!
> > lines? In a script using "module const" there may or may not be a
> > single line
> > import const
> > for explicitness (the alternative is having it performed implicitly
> > at startup, e.g. by sitecustomize.py &c &c, placing const in the
> > __builtin__ module, of course). That's up to the "experienced
> > developer" who decides constants are necessary at his/her site.
>
> Heaven forefend the newbie using what is generally considered good
> programming experience from the start. Let them develop the bad habbit of
> using magic numbers and other obscurities and then, once the bad habbit
> is ingrained, introduce the idea of consts with meaningful names... Wow,
> wish i'd thought of that!. Maybe it was my mistake, but I was under the
> impression that one of Python's objectives was to be a teaching language.
> Better to teach good practice from the start isn't it?
Sure, and good practice is to NOT rebind what should not be rebound
rather than do it with abandon and rely on a compiler to rap your
knuckles for it, because the compiler will NOT be able to catch ALL
of your wanton rebindings anyway. Good practice is also to be fully
explicit about what you're doing, whence the "import const" is a
move FOR good practice. A bare identifier without indication of where
it's coming from -- is it rebindable or not? You can't tell -- there is
NO localized indication in the identifier itself. What advantage do you
purport for having rebindable and non-rebindable identifiers look
exactly the same? const.something clearly and locally indicates "hey
guy, I'm not rebindable". Now *THAT* is good practice.
And please don't imply I like "magic numbers or other obscurities"
just because I loathe, detest, abhor and reject your "alias" proposal
(the specific killer is the use of ":" -- with an equal sign it would just
be an ordinary bad proposal, the colon makes it truly horrid). I like
things being NAMED more often than not -- well chosen names are
a big help. But Python's existing naming mechanisms are good and
fully sufficient to teach beginners good practices, including that of
"just don't do it" as opposed as "the language is your nanny and will
spank you whenever you do something naughty". Adding a "const"
module, for non-rebindable constants which need global scope, is
not necessarily a bad idea -- such needs do arise, and if one must
have globals it IS better to make them non-rebindable when that
is at all feasible. But it's very far from needing to add a new kind
of statements -- much less one ripe with strangeness wrt all of
the rest of the language...!
> (Sorry, the word is "extraneous" - i'm a prgammer not a dictionary :). I
> actually do spend considerable time on longer posts proofing.)
Wasn't meant to be a spelling flame -- just a doublecheck in case you
were trying to say something different and I had misunderstood.
> > > with more lines of code, not to mention the antics needed to do
something
> > > that should be as simple as possible (imho).
> >
> > What "antics"? If you want 'const' to be activated by default
> > in every Python installation (e.g. in site.py), write a PEP
> > proposing just that. You DO realize, of course, that no matter
> > what little chance such a PEP may have, it IS going to be at
> > least a thousand times more likely to be adopted than anything
> > that will introduce a new keyword and thereby break perfectly
> > working code -- that's something that can *possibly* happen
> > only for really momentous developments (such as the new proposed
> > "yield" keyword-statement for generators) which DESPERATELY NEED
> > a new statement (can't POSSIBLY work halfway-decently without).
>
> Why? Is there something you know about how well new ideas are viewed by
> the core python team that I don't? I guess we'll never see the
Apparently, there is... "first, do no harm" is close to a prime directive
(*RARE* blotches such as print>>blah notwithstanding).
> introduction of another Python keyword like... hmm... "do" since it might
> break perfectly working code? I'd be clever here and point out in Latin
> that languages that don't grow die... but I don't know Latin since it's
> dead!
Oh, do you know all non-dead languages? Wow -- must be many
thousands of them right? Funny enough, Latin (and to a lesser
extent Greek and Sanskrit) are known far more widely than all but
a handful of "living" languages. Check, just for an example,
http://www.yle.fi/fbc/latini/index.html -- "Bush Europam circumit",
"Novum Regimen Britanniae", and other news of the day in the
sweetly artificial and elegant tongue of Caesar and Cicero (which
never really was Latin as people *spoke* it, of course).
Sigh, it seems we're both ramblers at heart, whence all of the
asides. Back to our muttons -- a language can grow in many and
important ways WITHOUT breaking working code. Python only
introduces incompatible changes *MOST CAREFULLY* -- either
when a previously tolerated practice was anyway bad and it was
deprecated in the docs (which can hardly apply to any use of a
perfectly ordinary word which is slated to become reserved!),
or in *TRULY MAJOR* circumstances where there is really no
way new functionality can be supplied well WITHOUT the use of
a new keyword. I think the proposed 'yield' is the first new
keyword that stands a chance of making it into Python in MANY
years -- it does meet both key criteria (truly major, no real
semi-decent alternative). 'alias', IMHO, has _less_ chance than
a snowball in hell (the latter *might* happen to end up in one
of the _frozen_ circles, after all!). But note that channeling
Guido is NOT my specialty -- gotta ask the timbot for that.
> Frankly, while it might not be as DRAMATIC as GENERATORS, in it's own
> quiet way, *I* think it's just as momentuous.
You think the differences in functionality offered between const.foo=bar
and alias foo:bar are as momentous as generators?! Oh my.
> (As for "yield" - whatever
> does a generator need yield for? My understanding of generators is that
> they produce a new value based on retained state, not actually generate a
> huge sequence - oops, there I go digressing again.)
Yes, and? Every yield "suspends" or "freezes" the state, ready for
the _next_ "new value" when it will be requested.
> I don't see this as anything as earthshaking as introducing nested scope
> which is going to cause far more problems in changing program structure
> (when it becomes the default) then changing the name of an identifier.
> Nor do I think that this is the first new keyword that was introduced
> since the inception of Python - of course, not having done the research
> to find 1.3 or earlier if they're publically available, I won't make such
> a bald statement.
I said "years", not "decades". Python's inception dates back to 1990,
after all.
> > > One can certainly argue that this is syntactical sugar. It does
however
> > > serve a multitude of good purposes among which are: maintainability;
> > > clarity; consistancy; correctness; good programming habbits; - a not
> > > inconsiderable set of advantages for a little sugar.
> >
> > I fail to see ANY of these advantages when comparing your "alias"
> > with a "const" module installed by site.py. How is
> > alias magic : 23
> > more maintainable, clearer, more consistent, more correct, or
> > a better programming habit than
> > const.magic = 23
> > ?!?! Please bring SOME kind of argument for such extraordinary
> > assertions... your bald statements are not "support" for them!
>
> I suggest you read an introductory book on good programming practice. If
> you fail to see any of these advantages, then I shudder to think about
> your code quality. Seriously, please bring SOME kind of argument for
> saying that such notions are NOT a better programming habbit then... etc.
*WHAT* "such notions" are you blabbering about? We're comparing
your proposed horror, "alias magic:23", versus the sane alternative of
"const.magic=23". What *NOTIONS* are involved in "favour" of your
absurdity? And if you want to go into flames and ad hominem attacks,
dear fellow, I think you've met your match. I *shouldn't* waste my
time flaming total unredeemable idiots, and it will make Steve Holden
cry, but hey, there IS a limit to the amount of idiocy and insults one
can tolerate, isn't there? I DO fail to see ANY advantage at all for your
proposal, which I consider a serious contender for the title of worst
language-modification-change suggestion of the year (among many
other worthy contenders of course), compared to the obvious low-key
alternative of having site.py (or sitecustomize.py) "install" a const
module in sys.modules (and optionally in __builtin__ -- I'm neutral
about that last part). I believe the syntax you propose is despicable,
the semantics inferior, the invasiveness on the language an obvious
problem that even an average opium addict would not have failed to
notice (suggesting that your awareness is below that of said average
opium addict:-), AND your shudders about the quality of the code I
write (with or without const.blah:-) insulting, idiotic, and uncalled for.
There -- so much for diplomacy.
> How is your suggestion that a new user:
> 1. Figure out how to import a feature that's inherantly available
> in many other programming languages.
Learn to read, jerk -- you just QUOTED it, ferchrissakes!
> > with a "const" module installed by site.py. How is
^^^^^^^^^^^^
If it's installed by site.py, ***WHY*** would a new user have
to "figure out how to import" it?! CHEEZ...
> 2. Make sure to not ever change any variable meant to be constant.
Did you MAJOR in this kind of behavior, or does it come natural to
you? If you ever *TRY* to rebind an attribute in const, an exception
is raised, just as if you ever try to divide by zero, or use a variable
that doesn't exist. Have you READ the const.py code I posted?!
Have you *UNDERSTOOD* it, or is it your normal behavior to
go around proposing changes to a language you understand so
well as to be unable to understand what a few lines of elementary
code in the language *DO*, when such lines are served to you on
a plate (since apparently you were unable to come up with
them yourself)? I spell it out AGAIN, just in case endless repetition
can finally penetrate your apparent drunken stupor: if site.py
installs const, a new user will have to 'make sure' he or she never
rebinds const attributes in exactly the same sense in which he or
she makes sure that he or she never divides by zero nor uses a
non-existent variable -- if the errant behavior happens, Python
raises an exception. This is how all errors are diagnosed in Python.
> 3. Figure out why the program won't work when const.magic magically
> changes because they imported a module that changed it without notice or
> warning.
See point 2. If the module they import tries to rebind an attribute
of const that is already bound, there will be an exception.
> 4. How are you going to ensure that developers are going to
> indentify every "meant to be constant so don't use this identifier as a
> constant" constant that they create? Heck, you can't even get programmers
> to do comments reliably and that's built in now! Forstalling the obvious
> argument, of course there is nothing that ensures that any developer is
> going to practice safe programming and use an alias... this isn't meant
> to legislate against stupidity (who was that king that decreed that the
> tide not come in?) but rather to facilitate doing things more correctly.
> any better then what i've proposed?
You claim *ADVANTAGES* for your 'alias' horror versus the obvious
"const installed by site.py" solution, bubba. *ADVANTAGES*, get it?
You want to break working code (see below), *SHOW* me the huge
pluses your proposal gives, that make it worth breaking good code (ha).
Now you're arguing that your wretched "alias" has no DISADVANTAGES
on this specific point wrt "const" -- neither can in any way force any
developer to use it. Let's say they're even on this score -- how does
this justify your extraordinary claim of *advantages* for your horrid
proposal wrt const?! And more, your SHUDDERS at my code's quality?
Do you think that to write good code one must be just as confused
as you are and claim a "lack of disadvantages" as an *ADVANTAGE*?!
> > > Finally, this wouldn't break any code,
> >
> > Puh-LEEZE. *ANY* use of 'alias' in existing code would be
> > broken. Let's not make such obviously-false assertions...
>
> Yeah, that was my error - of course anyone can use "alias" as an
> identifier. I refer you to my previous remarks with respect to changes in
> Python since the first version, above. At least, unlike the recent furor
> over changing the semantics of "print", this is new.
Nihil sub sole novi. Just about every stupid change to Python is
requested over and over and over again on this newsgroup (hardly
ever with the needed Python Enhancement Proposal followup, to
be sure) -- often there is a quirk (here, specifically, that crazy use
of ':'), but the substance is just about always the same. People
who don't fully understand a language, yet, instead of striving for
comprehension (which is NOT all that hard in Python's case),
start blabbering to CHANGE it!
> > Alex
>
> Fred
>
> P.S If you're confused by "Fred", I changed my identifier - oops, did I
> forget to mention that in the docs?
I think this was one of your smartest moves -- if you can manage to
change your name, maybe you can live down the shame of this
"alias" proposal. Shudder at my code's quality, will you...?
Alex
Takes some work, and is untested, but...:
import types,sys
class ListSlice:
def __init__(self, alist, start, stop=None):
self.alist=alist
self.start=start
self.stop=stop
def __stopper(self):
if self.stop is None: return len(self.alist)
else: return self.stop
def __normindex(self, index, aslice=0):
if index<0:
result = self.__stopper()+index
else:
try: result = self.start+index
except OverflowError:
if aslice==2: return self.__stopper()
raise
if self.start<=result<self.__stopper():
return result
else:
if aslice==1: return self.start
elif aslice==2: return self.__stopper()
else: raise IndexError, result
def __sliceit(self, index):
if index.step is not None:
raise TypeError, "sequence index must be integer"
newstart = self.__normindex(index.start,1)
newstop = self.__normindex(index.stop,2)
return newstart, newstop
def __len__(self):
return max(0, self.__stopper()-self.start)
def __getitem__(self, index):
if type(index)==types.SliceType:
newstart, newstop = self.__sliceit(index)
return self.alist[newstart:newstop]
else:
return self.alist[self.__normindex(index)]
def __setitem__(self, index, value):
if type(index)==types.SliceType:
newstart, newstop = self.__sliceit(index)
self.alist[newstart:newstop] = value
else:
self.alist[self.__normindex(index)] = value
>> base = list("prolegomena")
>> slic=ListSlice(base,2,6)
>>> ''.join(slic)
'oleg'
>>> ''.join(base)
'prolegomena'
>>> slic[:3]
['o', 'l', 'e']
>>> slic[2:]
['e', 'g']
>>> slic[1:4]
['l', 'e', 'g']
>>> slic[1:3]
['l', 'e']
>>> slic[1:3]=list("plop")
>>> ''.join(base)
'proplopgomena'
>>> ''.join(slic)
'oplo'
>>>
As you see, it itsn't perfect -- the slice should no doubt
adjust its length in some more circumstances, the better
to mimic a built-in sequence, specifically when it's subject
to slice-assignment. But I hope it can get you started.
Alex
Tx for the 'excellent':-).
> > One (IMHO) Python enhancement would be to give dictionaries
> > some finer-grained control on their degree of mutability.
> > The ability to selectively make SOME existing keys non
> > rebindable and/or non removable _would_ come in handy in
...
> now, that's an interesting idea.
> how would that look, syntactically?
Haven't thought about in PEP-sufficient details...:-)
> dict['A']=1
> dict.lock('A')
>
> ..making the value unchangeable?
Un-rebindable, to be precise -- i.e.:
dict['A'] = list("ciao")
dict.setlock(1, 'A')
dict['A'].append("plip")
print dict['A']
ciaoplip
would work -- so the value is still changeable in the sense of
'mutable'. Sorry, this IS a pedantic distinction, but it can be
important. What I (somewhat vaguely) had in mind was a
.setlock() method (it may be important to have a .getlock one
for introspection, too) able to associate 'lock-bits' with...:
-- specific keys,
-- all keys in the dictionary,
-- all keys NOT in the dictionary
and the lock-bits might inhibit one or more of:
-- binding
-- rebinding
-- deleting
-- changing the lockbits themselves
and that's where it bogged down last time (before we got to
the syntax) -- my correspondant was appalled at the idea of
using 'bits' to overtly encode 'a set of options' and I could
not find an alternative, as Python lacks 'sets'.
Assuming one can stomach 'bits' (or some, e.g., encoding
as string thereof, such as the mode parameter to 'open'),
putting the bits first in setlock has the advantage that the
other parameters to setlock can be optional. So...:
dict.setlock(n)
sets bits n as the lockbits for all keys not in the dictionary,
dict.setlock(n, 'A')
sets bits n as the lockbits for key 'A' (which must be in
the dictionary right now, else KeyError is raised),
dict.setlock(n, 'A', 'B', 'C')
sets bits n for three keys,
dict.setlock(n, *dict)
sets them for all keys currently in the dictionary if a dictionary
can be used as a sequence (as seems to be true in Python 2.2).
A dictionary whose lockbits are set to forbid ANY rebinding,
deleting, new-key binding, AND change to the lockbits, could
suddenly and logically sprout hashability, since it becomes an
acceptable key IF it has hashable values (much like a tuple --
if the items are changeable, the fact that the _container_ is
not does not suffice). But that's an aside, I guess.
> ..and would attempts to set the value raise an exception?
Exactly -- that seems to be the only Pythonic approach. The
key added-value of this hypothetical proposal would be to
help you avoid accidental rebinding or deletion, or accidental
addition of new keys, to a dictionary that you have decided
must not be further changed in such ways.
For example,
sys.modules[__name__].__dict__.setlock(n)
or if supported (if globals() WAS defined as equivalent...):
globals().setlock(n)
for an appropriate n would say "no more new keys can be
bound in the current module's dictionary" -- giving much
of the effect of optional "variable declarations" for the
global variables of this module. Not the most crucial
need in the world, but I think it WOULD be a helpful
psychological crutch to know you COULD do that if needed,
to get Python more widely accepted. And no special purpose
machinery would be needed -- just an application of various
useful mechanisms in orthogonal ways... very Pythonic IMHO.
Easy to dress up in a function of course, as would be some
other construct such as
magic=23
globals().setlock(n,'magic')
to make magic a non-rebindable "constant". Etc, etc.
Alex
I like to repeat this every two years or so <wink>: four keywords have been
added to Python, but only one after 1.0 was released (in January of 1994),
and very few knew that another one existed.
First "exec" was changed from a builtin function to a statement. This was
done because exec can create new local vrbls, and it was impossible to get
the scoping straight in all cases without letting the compiler know exactly
when an exec could happen (BTW, a similar argument applies to yield wrt
Jython, although Guido lacked the foresight to make yield a builtin function
before 1.0).
"lambda" was added for the 1.0 release. Guido still regrets it <0.9 wink>.
"access" was added sometime or other, but it was never documented, never
advertised, rarely admitted, and eventually went away again(!). It was a
gimmick for adding piles of visibility controls to class and instance
attributes; the implementation was terribly complicated, so failed the "if
the implementation is hard to explain, it's a bad idea" test, and Guido
never felt happy enough with it to admit its existence in public.
That leaves the only post-1.0 addition, "assert". It took years to get that
in -- although it's hard now to remember exactly why. The primary reason
it's a keyword is so the compiler can eliminate it under -O.
Guido should have made "keyword" a keyword too. Then we could have had a
keyword statement at the top of each module, identifying all the post-1.0
keywords your code wants to use <0.9 wink>.
> 'alias', IMHO, has _less_ chance than a snowball in hell (the latter
> *might* happen to end up in one of the _frozen_ circles, after all!).
> But note that channeling Guido is NOT my specialty -- gotta ask the
> timbot for that.
I'm not sure that the Dutch vision of hell coincides with Dante's, so in the
interest of not ruffling any international feathers, I'll just say it stands
about as much chance as a drunken virgin in Amsterdam.
Almost all Python code "spells a constant" via
UPPERCASE_NAME = some_expression
and in 10+ years of Python practice I've never rebound such a name by
accident -- or heard of anyone else doing so either. This isn't C, and e.g.
we don't have the
if (OOPS = 3)
flavor of accidental rebindings. Neither does Python have pointers or an
address-of operator, nor a call-by-reference mode, etc. You just can't put
a name in a binding context by accident in Python, except for stumbling into
the
except ValueError, OverflowError:
wart, and UPPERCASE_NAME is very unlikely to appear in that context.
"const frameworks" get invented routinely, but their inventors appear to
drop them after the heat of argument fades. Why bother? A universal
convention supplies all of maintainability, clarity, consistency, and a
foundation for good programming habits too. What it doesn't do is insist
that you follow it against your will. That's Python!
Guido once said that protection mechanisms in Python are like bicycle locks
in Amsterdam: they're advisory. If you're not working with reasonably
mature consenting adults, look into the rexec and Bastion modules for ways
to *really* frustrate your errant coworkers. If you can't trust *yourself*
to adhere to simple conventions, though, Python isn't your language.
otoh-keep-using-it-and-you'll-change-so-that-it-is<wink>-ly y'rs - tim
Not sure I understand that motivation... the compiler under -O can
eliminate non-keyword stuff too:
D:\py21>python -O
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
Alternative ReadLine 1.4 -- Copyright 2001, Chris Gonnerman
>>> def f():
... print 'before'
... if __debug__:
... print 'inside'
... print 'after'
...
>>> import dis
>>> dis.dis(f)
0 LOAD_CONST 1 ('before')
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 2 ('after')
8 PRINT_ITEM
9 PRINT_NEWLINE
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>>
...the whole "if __debug__:" statement being 'eliminated', no? I do
understand that identifiers with __ in front and back are 'sort of
reserved', but, not keywords, aren't they? I'm *NOT* arguing against
assert, mind you -- one of my favourite statements -- just trying for
better understandings of the why's and wherefore's.
> Guido should have made "keyword" a keyword too. Then we could have had a
> keyword statement at the top of each module, identifying all the post-1.0
> keywords your code wants to use <0.9 wink>.
That COULD be done by having the module assign a literal to
__keywords__ at the top -- the leading & trailing underscores
making it magic and 'reserved', no 'clean' code can get
broken (for some definition of 'clean'). Despite that missing
wink-fraction, this doesn't appear to be highly Pythonic though.
> "const frameworks" get invented routinely, but their inventors appear to
> drop them after the heat of argument fades. Why bother? A universal
In my case, mostly a (vain) hope of stifling a yet-one-more-round-of-
"enhancement"-demands. Silly of me to hope, but...
> convention supplies all of maintainability, clarity, consistency, and a
> foundation for good programming habits too. What it doesn't do is insist
> that you follow it against your will. That's Python!
>
> Guido once said that protection mechanisms in Python are like bicycle
locks
> in Amsterdam: they're advisory.
That's what a __setattr__ method in a class does inter alia -- it ADVISES
against not-meant-to-happen accidental bindings/rebindings (by raising
an exception) while still letting you access the __dict__ when you really
need to get around it. A pure convention is weaker than an advisory
mechanism. There is no advisory mechanism for "constants" (except as
attributes in a suitable object) -- JUST the convention. That may be
a tad too weak in some cases (I'm neutral on that). It sure discourages
some people from learning enough Python to see it doesn't matter.
The advisory __whatever mechanism, which supplemented the purely-
conventional _whatever one, did help to make a couple Python converts
in my experience already -- they'd walk away BUT, when they saw there
WAS a way to make stuff private-enough (C++'ists DO know that deep
down there's no real guarantee, just convention;-), they kept going for
long enough to see it's not a big issue either way. I suspect similarly
weak-but-not-totally-inexistent mechanisms for other kinds of advisory
protection would have similarly positive effect.
> to *really* frustrate your errant coworkers. If you can't trust
*yourself*
> to adhere to simple conventions, though, Python isn't your language.
>
> otoh-keep-using-it-and-you'll-change-so-that-it-is<wink>-ly y'rs - tim
That's why it's worth luring people into Python with bait-and-switch
tactics IMHO.
Alex
Well, I think you're kidding, but this should be part of a more general directive
system. :)
C//
<much tedious and boorish diatribe elided>
In article <9gf43...@enews1.newsguy.com>, ale...@yahoo.com says...
> "Novum Regimen Britanniae
Dream On.
> But note that channeling
> Guido is NOT my specialty -- gotta ask the timbot for that.
No, it's pretty clear what your speciality is...
> > (As for "yield" - whatever
> > does a generator need yield for? My understanding of generators is that
> > they produce a new value based on retained state, not actually generate a
> > huge sequence - oops, there I go digressing again.)
>
> Yes, and? Every yield "suspends" or "freezes" the state, ready for
> the _next_ "new value" when it will be requested.
Why would you need to yield something that gets called upon to produce
the next value in a sequence and then is dormant until the next time it's
called upon?
Most people I know who are programmers associate "yield" with something
that one does in order to relinquish execution to another process or
thread.
> I said "years", not "decades". Python's inception dates back to 1990,
> after all.
I said neither "years" or "decades" - BTW, 1990 - 2000 is a decade last
time I checked: has the OED a different definition?
> And if you want to go into flames and ad hominem attacks,
> dear fellow, I think you've met your match.
Oh goodness no! If you want the title of "Best Flamer", you're quite
welcome to it! You seem to do it so well too! (Are you by any chance
Quentin Crisp's sister?)
> > > Alex
When a brisk (actually pretty enjoyable - not often I get to have an
exchange with someone who appears to have something interesting to say
and also says it in an interesting way), somewhat snippy (on both sides)
discussion suddenly turns into preemptive projectile diarrhea of the
mouth, one has to wonder if there was any real substance behind the
dialog in the first place.
Thank goodness I didn't mention the "p" word!
Dave
> 'def', while not an assignment per se, has the same semantics as assignment,
> i.e. a name bound with 'def' can be rebound with assignment and vice versa.
Which has bitten me recently when I accidentally gave two methods
the same name. The one written later silently replaced the other.
Fortunately they had different numbers of parameters so the error
was caught on a call to one of them.
--
__("< Marcin Kowalczyk * qrc...@knm.org.pl http://qrczak.ids.net.pl/
\__/
^^ SYGNATURA ZASTĘPCZA
QRCZAK
> Takes some work, and is untested, but...:
...snipped code
> As you see, it itsn't perfect -- the slice should no doubt
> adjust its length in some more circumstances, the better
> to mimic a built-in sequence, specifically when it's subject
> to slice-assignment. But I hope it can get you started.
>
Many thanks and much awe...
Andy
On the contrary, there is something that prevents me from reassigning
identifiers intended as constants: the fact that it's a silly think to
do.
That should read "if something:".
I think 'is true' is bad for a few reasons:
- You rely on an implementation detail, namely that two instances of the
number 1 will be interned to the same object; that might change.
'== true' is better.
- 2 and "whee" are just as much true in Python, but your 'if' treats them
as false.
- Something like 'if (a and b) is true:' does not do what it seems to do,
since boolean operators don't return 0 or 1, except for 'not'.
- The whole test for truth is redundant, since that's what 'if' does...
For these reasons, never make #defines (aliases) for true and false.
More in general, your constants are just variables that look like variables
but are protected from rebinding. That's just not in the Python spirit, imo.
Just use some convenction like ALL_CAPS and then don't rebind them...
I think you don't have much experience with Python yet, but come from some
other language and think you see something missing. In your example aliases,
you called a dictionary a tuple (I believe that was you, anyway)... Just code
Python for a while and see that it is never a problem.
> Finally, this wouldn't break any code, nor would anything (excepting
> perhaps peer pressure) force anyone to use it.
Introducing a new keyword always breaks lots of code.
--
Remco Gerlich
true = not None
true = not 0
true = not None and not 0
are all completely equal to
true = 1
So I'm completely confused about what you want with that statement.
--
Remco Gerlich
But does that belong in *Python*? Where you can delete builtin functions,
add and remove methods to classes on the fly, change any imported module's
functions from the outside, change a class' parent classes, change an
instance's class... *Nothing* is restricted in Python.
That's what the language is about. It comes from the view point that
programmers are mature individuals who can be held responsible for their own
actions. As for newbies, it teaches them that they have to think for
themselves, and that coding style guides (like ALL_CAPS for things you
shouldn't change, or starting a method name with _ if it shouldn't be called
from the outside) are Good Things. It's explicit, not only at the place
where the thing is defined, but also where it is used! Readable.
Adding a way to block rebinding of a name would be a horribly inconsistent
wart on the language.
> > When I hear that phrase, I reach for my gun. Go and use Pascal or
> > Eiffel if you're into bondage-and-discipline.
>
> Oh god am I tempted... but i'll refrain.
Why? I really don't see how you could find Python usable. Please, if a
language has a philosophy almost totally opposite from yours, go find a
language that better suits your needs instead of starting a flamewar in
comp.lang.python trying to fundamentally change the language...
--
Remco Gerlich
I think this is a slight overbid. It is perfectly possible in Python to
"block rebinding" of an object's attribute (__setattr__ easily allows
that), after all, yet the sky hasn't fallen. One could similarly allow
blocking the rebinding of a container's item (you can do that for a
user-defined container, with __setitem__, though not on dictionaries
or lists -- tuples do "block the rebindinding" of their items). Such
'blocking' is occasionally useful to help avoid accidental rebinding
of things that are not meant to be rebound.
Thus, I do not believe it would at all be "a wart of the language" if
Python was very slightly extended to either allow a user-defined
mapping object to be set as the __dict__ attribute of a module
(where now a bona fide dictionary must be used instead), or to
make builtin dictionaries slightly more powerful (adding a method
that let them block rebinding of some of their items).
With either of these slight extensions, there WOULD then most
naturally emerge "a way to block rebinding of a name" in every
case in which the namespace is a dictionary (not necessarily for
local variables of a function -- the local-namespace optimization
impedes many generalizations of this kind, of course, although
it's apparently indispensable for performance reasons).
And what would be wart-y about it *at all*? Isn't it rather a
small wart that a user-defined mapping CANNOT be used for
any role for which a real-dictionary can...?
Alex
It's just occurred to me that using this facility, you could
implements constants in python withoput having to change the
language, by having a CONST function:
CONST("PI", 3.14159)
this will put a new item in the current environment's dictionary,
PI, with the relevant value, just like PI = 3.14159 had been executed.
It will also override the __setattr__ function so that any attempt
to reassign PI will throw an exception. of course, there would
be performance penalties.
>Thus, I do not believe it would at all be "a wart of the language" if
>Python was very slightly extended to either allow a user-defined
>mapping object to be set as the __dict__ attribute of a module
>(where now a bona fide dictionary must be used instead),
Ah -- does that mean my idea won't work?
If user objects were allowed as a module's __dict__, and/or if
built-in dictionaries allowed selective locking of entries, you could
do that (if by "current environment" you mean the GLOBAL one --
a function cannot add entries to its caller' LOCAL namespace, in
general... only a statement can do that). In Python 2.1 at least,
you can do that in a dedicated "module" (let's call it 'const' for
definiteness), actually implemented as an instance -- I showed
similar ideas repeatedly in this thread. Things could be set up
as to allow a more natural
const.PI = 3.14159
to be completely equivalent to your hypothetical CONST function
(if your CONST could bind and lock a variable in its caller's global
namespace, so could const.__setitem__, of course).
> >mapping object to be set as the __dict__ attribute of a module
> >(where now a bona fide dictionary must be used instead),
>
> Ah -- does that mean my idea won't work?
In Python 2.1 at least (and I doubt this will change in 2.2) it is
not yet possible to use a user-object as a module's dictionary,
nor do builtin dictionaries support selective locking. I suspect
the former stricture WILL eventually fall (as part of the long slow
march to overcome the type/class chasm), but I would not venture
a guess/prediction about the latter.
Alex
[Alex Martelli]
> Not sure I understand that motivation... the compiler under -O can
> eliminate non-keyword stuff too: [via __debug__]
Yes. But if assert were a builtin function instead, the compiler couldn't
know by magic that the user *wanted*
assert(x < y, "oops")
wrapped in an "if __debug__:" block, because the compiler can't know that
"assert" refers to the builtin function and not something else (btw, we have
to fix that someday! it's irritating). __debug__ was an implementation
mechanism created to *support* assert, and was-- in good Python
fashion --exposed so that adventurers could dream up other uses for it too.
__debug__ wasn't "the feature" here, though, "assert" was.
> ...
> A pure convention is weaker than an advisory mechanism. There is no
> advisory mechanism for "constants" (except as attributes in a suitable
> object) -- JUST the convention.
Yes.
> That may be a tad too weak in some cases (I'm neutral on that). It
> sure discourages some people from learning enough Python to see it
> doesn't matter.
Oh, the list of reasons people have for rejecting Python is as long as the
number of people who have bothered to report on it. There's too much to be
done that would help actual Python users to worry too much about determined
non-users.
> The advisory __whatever mechanism, which supplemented the purely-
> conventional _whatever one, did help to make a couple Python converts
> in my experience already -- they'd walk away BUT, when they saw there
> WAS a way to make stuff private-enough (C++'ists DO know that deep
> down there's no real guarantee, just convention;-), they kept going for
> long enough to see it's not a big issue either way. I suspect similarly
> weak-but-not-totally-inexistent mechanisms for other kinds of advisory
> protection would have similarly positive effect.
This is one of the functions the newsgroup serves, is it not? If anyone had
the determination to *search* first, they'd find these frameworks invented
and reinvented over & over in "confused newbie" threads. I'm not sure it's
the framework that wins them over in the end, though: often it appears more
the discussion that goes along with it. From that view, I'm not sure that
"canning" these frameworks would do as much good. If someone wants to try,
though, register it with the Vaults of Parnassus and have at it.
I'm having a lot of trouble with this proposal. I believe I am against parts
of it in principal, but am heavily in favour of the basic idea behind it
(which I have expressed before).
1. I am heavily against the use of the "alias:" syntax. However, I will use
the "alias" terminology here.
2. I am unclear about what is actually being proposed. I have seen
conflicting statements by Dave, so wish to clear it up. Please choose one of
the following.
a. An alias would perform a textual substitution before the code is compiled
(as in a C #define).
b. An alias would be evaluated where it is assigned/created, and thereafter
its value would be constant.
c. An alias would be evaluated using the local namespace each time it is
encountered, and the result used in the expression.
In my mind, (b) is a constant, and (c) is an alias. (a) should not even be
considered.
The root of the problem which I believe people are trying to solve is making
things provably constant. There are two things involved here:
1. Preventing a reference from being rebound.
2. Preventing a mutable instance from being modified.
Both of these are almost completely doable now.
1. Preventing a reference from being rebound:
As Alex has posted, and I agree, replacing a module with a restricted
__setattr__() does most of what we wish here. A perhaps better option though
would be to have a builtin object called "const". This has a few advantages,
and 1 disadvantage:
a. There is no need to "import const" (advantage).
b. It does not interfere with a module named "const" created by someone else
- local namespace takes precedence over builtin (advantage).
c. The __builtin__.__dict['const'] object could be replaced by something
else (normally a disadvantage). This could be changed by making
__builtin__.__dict__ not actually be a dictionary, but a class instance
which disallows rebinding certain references (such as "const").
2. Preventing a mutable instance from being modified
This could be done for class instances by an immutable() builtin function.
This function would change the __setattr__() function of the instance to one
which raises an Exception, and nothing else.
a. This would only work for class instances - not classes or types. With the
type/class difference going away, it comes down to only class objects having
problems with this. Until this difference goes away, lists could be
converted to tuples by immutable(), but dictionaries remain a problem.
b. Someone could get around the immutable() function by replacing the
__setattr__() method after it is called.
Tim Delaney
One concern: since dicts are crucial to Python's performance, we're loathe
to add any code to their critical paths, or more memory to the object.
Indeed, I spent a fair chunk of my life reducing the internal dict bloat
after 2.1 was released, and we got some nice speedups in return.
Provided Guido is successful in healing the type/class split, it should be
possible to subclass dicts (in Python or C), and you can make those just as
slothful as you can bear <wink>.
[Alex Martelli]
> ...
> my correspondant was appalled at the idea of using 'bits' to overtly
> encode 'a set of options' and I could not find an alternative, as
> Python lacks 'sets'.
> ...
> A dictionary whose lockbits are set to forbid ANY rebinding,
> deleting, new-key binding, AND change to the lockbits, could
> suddenly and logically sprout hashability, since it becomes an
> acceptable key IF it has hashable values (much like a tuple --
> if the items are changeable, the fact that the _container_ is
> not does not suffice). But that's an aside, I guess.
Earlier talk about freezing a dict actually started in relation to Greg
Wilson's PEP to add a set type to Python. He's implementing sets as dicts
under the covers, and so sets of sets (etc) require hashing (and freezing)
dicts. I don't think we have a slick solution for that. Right now a Set
instance sets a .frozen flag when its __hash__ method gets called, and all
the mutating Set methods check that flag at the start (raising an exception
if it's set). The problem is that the flag gets lit sometimes when it
needn't be; e.g., doing
if setA in setB:
shouldn't freeze setA forever. So hash() is a wrong thing to key on. OTOH,
dict[setA] = 42 *must* freeze setA's dict, and the only clue the Set type
has is that hash() gets called.
So look on the bright side: if you never get these bits, you'll never have
to wrestle with managing them either <0.8 wink>.
Yes, I understand this MUST be an overriding concern. Practicality
beats purity -- Python's speed is TOO dependent on dictionaries to
allow much play with them.
> Provided Guido is successful in healing the type/class split, it should be
> possible to subclass dicts (in Python or C), and you can make those just
as
> slothful as you can bear <wink>.
I think this points the way forwards. Subclassable dictionaries
will at least allow real-life experimentation -- this may help
determine whether some potential "further dictionary feature" is
[a] of widespread-enough interest *AND* [b] susceptible of fast-
enough, memory-spare implementation, to warrant considering for
"REAL" dictionaries.
> > A dictionary whose lockbits are set to forbid ANY rebinding,
> > deleting, new-key binding, AND change to the lockbits, could
> > suddenly and logically sprout hashability, since it becomes an
> > acceptable key IF it has hashable values (much like a tuple --
> > if the items are changeable, the fact that the _container_ is
> > not does not suffice). But that's an aside, I guess.
>
> Earlier talk about freezing a dict actually started in relation to Greg
> Wilson's PEP to add a set type to Python. He's implementing sets as dicts
> under the covers, and so sets of sets (etc) require hashing (and freezing)
> dicts. I don't think we have a slick solution for that. Right now a Set
> instance sets a .frozen flag when its __hash__ method gets called, and all
> the mutating Set methods check that flag at the start (raising an
exception
> if it's set). The problem is that the flag gets lit sometimes when it
> needn't be; e.g., doing
>
> if setA in setB:
>
> shouldn't freeze setA forever. So hash() is a wrong thing to key on.
OTOH,
Maybe setB's __contains__ could specialcase this particular issue,
but it would still be there for "if setA in somedict". My un-slick,
explicit-is-better-than-implicit approach would require *explicit*
locking/freezing as a necessary (not sufficient -- items need to be
right to) condition to make a dictionary hashable. Having __hash__
blackmagically trigger freezing sounds somewhat scary to me, just
as it would if (e.g.) it made a list into a tuple or thereabouts.
Alex
OTOH, there's been some discussion of locking dicts during certain
operations to prevent some ugly bugs and crashes. Given the amount of
code simplification that would generate overall, would it maybe make
sense to add an external interface to the locking mechanism?
--
--- Aahz <*> (Copyright 2001 by aa...@pobox.com)
Hugs and backrubs -- I break Rule 6 http://www.rahul.net/aahz/
Androgynous poly kinky vanilla queer het Pythonista
"It's not what you know, it's what you *think* you know." --Steve Martin
I second that. However, I think there's another issue
related to this: sometimes I'm discouraged from using
named values like this because of the relative
inefficiency of looking up globals as opposed to
locals.
Having a "const" syntax would be one way of addressing
this, since the compiler would have opportunities to
optimise.
Instead of introducing a new syntax, however, I'd rather
see some work done on the implementation of module
namespaces to make them more like local namespaces
are now -- i.e. so that names the compiler knows about
are accessed by indexing into an array instead of
looking up a dictionary.
I think this would be a much more worthwhile investment
of effort, since it would benefit *all* accesses to
globals, not just "constant" ones!
--
Greg Ewing, Computer Science Dept, University of Canterbury,
Christchurch, New Zealand
To get my email address, please visit my web page:
http://www.cosc.canterbury.ac.nz/~greg
I'm afraid "making opportunities" isn't that helpful unless they come with
working code to exploit them.
> Instead of introducing a new syntax, however, I'd rather
> see some work done on the implementation of module
> namespaces to make them more like local namespaces
> are now -- i.e. so that names the compiler knows about
> are accessed by indexing into an array instead of
> looking up a dictionary.
>
> I think this would be a much more worthwhile investment
> of effort, since it would benefit *all* accesses to
> globals, not just "constant" ones!
I agree. Jeremy was looking into this seriously, but the month he intended
to work on it got lost when paternity leave came a month earlier than
planned. So, blame God or not, but there's no bandwidth at PythonLabs to
look into this now. Would still make a good PEP.
> [Greg Ewing]
>>Instead of introducing a new syntax, however, I'd rather
>>see some work done on the implementation of module
>>namespaces to make them more like local namespaces
>>are now -- i.e. so that names the compiler knows about
>>are accessed by indexing into an array instead of
>>looking up a dictionary.
>>
>>I think this would be a much more worthwhile investment
>>of effort, since it would benefit *all* accesses to
>>globals, not just "constant" ones!
>>
>
> I agree. Jeremy was looking into this seriously, but the month he
intended
> to work on it got lost when paternity leave came a month earlier than
> planned. So, blame God or not, but there's no bandwidth at PythonLabs to
> look into this now. Would still make a good PEP.
I posted some notes on python-dev for a PEP I was working on before the
babies came:
http://mail.python.org/pipermail/python-dev/2001-May/014995.html
Subject: pre-PEP on optimized global names
I think the draft I posted there doesn't go into much detail about the
changes to the interpreter internals. I think there are a lot of issues
there, not least of which is that there is no builtin dictionary type that
represents the globals of a module. This is one instance of many changes
that programmers using the C API would need to cope with.
Perhaps 2.2 is the right time to make these changes, since the C API will
probably change a lot anyway. I don't know what the PEP deadline or alpha
release schedule is for 2.2, so it's hard to say if it's too late.
If someone wants to pick up these notes and draft a full PEP, I'd be
thrilled. I can't promise much help, although I'd like to.
Jeremy
I'm given to understand that, in the case of lists,
this is achieved by temporarily changing the type
pointer. If a similar thing were done for dicts,
presumably it wouldn't have any effect on the
performance of non-locked dicts.
> would it maybe make
> sense to add an external interface to the locking mechanism?
Hmmm... wild thought: after type/class healing,
every object will have a __class__ attribute...
if it were changeable...
d = {'spam':42}
d.__class__ = MyLockedDictClass
No, probably far too dangerous...
x = []
x.__class__ = 3.__class__
print x
<<<fireworks as python interpreter self-destructs>>>
Yes, it would (assuming I understand the discussion correctly), because
the code would be simplified by not needing the smarts to deal with
dicts mutating in the middle of operations. I don't really know enough
to understand what I'm talking about, but it occurred to me that
possibly it might make sense to directly implement locked dictionaries
and then have the internals use the external API under the covers.
(You'd need a second "can't unlock this dict" variable for internal use,
but that would only slow down the dict.unlock() operation.)
All together now....
duh-duh-duh-duh duh-duh duh-duh <can't touch this!>
(ok... it's been a long week so far...)
--
Emile van Sebille
em...@fenx.com
---------
[Greg Ewing]
> I'm given to understand that, in the case of lists, this is achieved
> by temporarily changing the type pointer. If a similar thing were done
> for dicts, presumably it wouldn't have any effect on the performance of
> non-locked dicts.
No rational effect, anyway. For example, if you wanted a dict that refused
to delete items, give it a type object almost exactly like a regular dict's,
except redirect its tp_as_mapping slot to a PyMappingMethods struct with a
custom mp_ass_subscript slot (that makes more sense if you look at the code
<wink -- but this is just CPython's current way of faking inheritance in C,
at the level of hand-coded vtables>). They can share the rest of the dict
implementation, and modulo "cache effects" this should have no effect at all
on regular dict speed.
But note that there's really no way to do this without editing dictobject.c:
unlike *most* of the Python types, the representation of dicts can't be
gotten from an #include file. They're one of Python's few true "black box"
types at the C level, and that's deliberate (the internal representation of
dicts has changed frequently, and has changed again for 2.2 -- but since it
was never available outside dictobject.c, nothing will break).
> Hmmm... wild thought: after type/class healing,
> every object will have a __class__ attribute...
> if it were changeable...
>
> d = {'spam':42}
> d.__class__ = MyLockedDictClass
>
> No, probably far too dangerous...
>
> x = []
> x.__class__ = 3.__class__
> print x
>
> <<<fireworks as python interpreter self-destructs>>>
On descr-branch:
>>> [].__class__
<type 'list'>
>>> [].__class__ = type(2)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: readonly attribute
Assigning to (3).__class__ or "a".__class__ would actually be much
more insidious...
Cheers,
M.
--
This makes it possible to pass complex object hierarchies to
a C coder who thinks computer science has made no worthwhile
advancements since the invention of the pointer.
-- Gordon McMillan, 30 Jul 1998