"no variable or argument declarations are necessary."

Bengt Richter bokr at oz.net
Thu Oct 6 02:57:09 EDT 2005


On Wed, 05 Oct 2005 11:10:58 GMT, Ron Adam <rrr at ronadam.com> wrote:

>Antoon Pardon wrote:
>> Op 2005-10-04, Ron Adam schreef <rrr at ronadam.com>:
>> 
>>>Antoon Pardon wrote:
>>>
>>>>Op 2005-10-03, Steven D'Aprano schreef <steve at REMOVETHIScyber.com.au>:
>>>>
>>>>>And lo, one multi-billion dollar Mars lander starts braking either too
>>>>>early or too late. Result: a new crater on Mars, named after the NASA
>>>>>employee who thought the compiler would catch errors.
>>>>
>>>>
>>>>Using (unit)tests will not guarantee that your programs is error free.
>>>>
>>>>So if sooner or later a (unit)tested program causes a problem, will you
>>>>then argue that we should abondon tests, because tests won't catch
>>>>all errors.
>>>
>>>Maybe you need to specify what kind of errors you want to catch. 
>>>Different types of errors require different approaches.
>> 
>> 
>> I want to catch all errors of course.
>
>Yes, of course, and so do other programmers.  What I mean is to try and 
>break it down into specific instances and then see what the best 
>approach is for each one is.
>
>When I first started leaning Python I looked for these features as well, 
>but after a while my programming style changed and I don't depend on 
>types and names to check my data near as much now.  But instead write 
>better organized code and data structures with more explicit value 
>checks where I need them.
>
>My concern now is having reusable code and modules I can depend on.  And 
>also separating my data and data management operations from the user 
>interface.  Having functions and names that don't care what type the 
>objects are, makes doing this separation easier.
>
>Another situation where typeless names are useful is routines that 
>explicitly check the type, then depending on the type does different 
>things.  For example if you have a list with a lot of different type 
>objects stored in it, you can sort the contents into sublists by type.
>
>Looking at it from a different direction, how about adding a keyword to 
>say,  "from this point on, in this local name space, disallow new 
>names".  Then you can do...
>
>def few(x,y):
>    a = 'a'
>    b = 'b'
>    i = j = k = l = None
>    no_new_names
>    # raise an error after here if a new name is used.
>    ...
>    for I in range(10):   <--  error
>       ...
>
>This is more suitable to Pythons style than declaring types or variables 
>I think.  Add to this explicit name-object locking to implement 
>constants and I think you would have most of the features you want.
>
You can do that now with a decorator, if you are willing to assign something
to no_new_names (so it won't give you a name error if it doesn't exist). E.g.,

 >>> def nnn(f):
 ...     names = f.func_code.co_names
 ...     assert 'no_new_names' not in names or names[-1]=='no_new_names', 'Bad name:%r'%names[-1]
 ...     return f
 ...
 >>> @nnn
 ... def few(x,y):
 ...     a = 'a'
 ...     b = 'b'
 ...     i = j = k = l = None
 ...     no_new_names=None
 ...     for i in range(10): print i,
 ...
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 3, in nnn
 AssertionError: Bad name:'range'
 >>> @nnn
 ... def few(x,y):
 ...     a = 'a'
 ...     b = 'b'
 ...     i = j = k = l = None
 ...     no_new_names=None
 ...     return a,b,i,j,k,l
 ...
 >>> few(123,456)
 ('a', 'b', None, None, None, None)

No guarantees, since this depends on the unguaranteed order of f.func_code.co_names ;-)

>so...
>
>     no_new_names     # limit any new names
>     lock_name name   # lock a name to it's current object
That last one you could probably do with a decorator that imports dis and
checks the disassembly (or does the equivalent check of the byte code) of f
for STORE_FASTs directed to particular names after the lock_name name declaration,
which you would have to spell as a legal dummy statement like
    lock_name = 'name'

or perhaps better, indicating a locked assignment e.g. to x by

    x = lock_name = expr  # lock_name is dummy target to notice in disassembly, to lock x from there on
>
>
>Since names are stored in dictionaries,  a dictionary attribute to 
>disallow/allow new keys, and a way to set individual elements in a 
>dictionary to read only would be needed.  Once you can do that and it 
>proves useful, then maybe you can propose it as a language feature.
I would want to explore how to compose functionality with existing elements
before introducing either new elements or new syntax. E.g., the dictionaries
used for instance attribute names and values already exist, and you can already
build all kinds of restrictions on the use of attribute names via properties
and descriptors of other kinds and via __getattribute__ etc.

>
>These might also be checked for in the compile stage and would probably 
>be better as it wouldn't cause any slow down in the code or need a new 
>dictionary type.
Although note that the nnn decorator above does its checking at run time,
when the decorator is executed just after the _def_ is anonymously _executed_
to create the function nnn gets handed to check or modify before what it
returns is bound to the def function name. ;-)
>
>An external checker could possibly work as well if a suitable marker is 
>used such as a bare string.
>
>     ...
>     x = y = z = None
>     "No_New_Names"        # checker looks for this
>     ...
>     X = y/z               # and reports this as an error
>     return x,y
>
>and..
>
>     ...
>     Author = "Fred"
>     "Name_Lock Author"    # checker sees this...
>     ...
>     Author = "John"       # then checker catches this
>     ...
>
>So there are a number of ways to possibly add these features.
Yup ;-)

>
>Finding common use cases where these would make a real difference would 
>also help.
>
Yup ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list