469,287 Members | 2,628 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,287 developers. It's quick & easy.

"no variable or argument declarations are necessary."

I am contemplating getting into Python, which is used by engineers I
admire - google and Bram Cohen, but was horrified to read

"no variable or argument declarations are necessary."

Surely that means that if I misspell a variable name, my program will
mysteriously fail to work with no error message.

If you don't declare variables, you can inadvertently re-use an
variable used in an enclosing context when you don't intend to, or
inadvertently reference a new variable (a typo) when you intended to
reference an existing variable.

What can one do to swiftly detect this type of bug?
--
http://www.jim.com
Oct 2 '05
134 6988
Paul Rubin wrote:
Brian Quinlan <br***@sweetapp.com> writes:
Have those of you who think that the lack of required declarations in
Python is a huge weakness given any thought to the impact that adding
them would have on the rest of the language? I can't imagine how any
language with required declarations could even remotely resemble
Python.


What's the big deal? Perl has an option for flagging undeclared
variables with warnings ("perl -w") or errors ("use strict") and Perl
docs I've seen advise using at least "perl -w" routinely. Those
didn't have much impact. Python already has a "global" declaration;
how does it de-Pythonize the language if there's also a "local"
declaration and an option to flag any variable that's not declared as
one or the other?


The difference is that perl actually needs 'use strict' to be useful for
anything more than trivial scripts. Without 'use strict' you can reference
any variable name without getting an error. Python takes a stricter
approach to begin with by throwing an exception if you reference an
undefined variable.

This only leaves the 'assigning to a different name than the one we
intended' problem which seems to worry some people here, and as has been
explained in great detail it incurs a cost to anyone reading the code for
what most Python users consider to be a very small benefit.

If you think variable declarations should be required, then you presumably
want that to cover class attributes as well as local and global
variables. After all assigning to 'x.i' when you meant 'x.j' is at least as
bad as assigning to 'i' instead of 'j'. But unless you know the type of
'x', how do you know whether it has attributes 'i' or 'j'? So do we need
type declarations, or perhaps we need a different syntax for 'create a new
attribute' vs 'update an existing attribute', both of which would throw an
exception if used in the wrong situation, and would therefore require lots
of hasattr calls for the cases where we don't care.

Oct 5 '05 #51
Op 2005-10-04, Ron Adam schreef <rr*@ronadam.com>:
Antoon Pardon wrote:
Op 2005-10-03, Steven D'Aprano schreef <st***@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.

I know that nothing will ever guarantee me this result, but some things
may help in getting close. So if a language provides a feature that can
help, I generally think that is positive. That such a feature won't
solve all problems shouldn't be considered fatal as some counter arguments
seem to suggest.

--
Antoon Pardon
Oct 5 '05 #52
en**********@ospaz.ru wrote:
Some people just don't get the simple fact that declarations are
essentially kind of unit test you get for free (almost), and the compiler
is a testing framework for them.


It seems you've missed the entire point of using a dynamically
typed language. It's not just about saving typing time and making
your methods take up fewer lines of code. It's about writing generic
code. Just look at C++ with all that mess with complex templates,
silly casting and dangerous void pointers etc that are needed to
achieve a fraction of the genericity that Python provides with no
effort from the programmer.

With properly written tests, you can be reasonably that the program
does what you want. Type declarations are extremely limited in this
aspect, and they often give programmers a false sense of security.
Oct 5 '05 #53
Duncan Booth <du**********@invalid.invalid> writes:
If you think variable declarations should be required,
I don't think they should be required. I think there should optional
declarations along with a compiler flag that checks for them if the
user asks for it, like Perl has.
then you presumably want that to cover class attributes as well as
local and global variables. After all assigning to 'x.i' when you
meant 'x.j' is at least as bad as assigning to 'i'
Yes, lots of people mistakenly use __slots__ for exactly that purpose.
Maybe the function they think __slots__ is supposed to implement is a
legitimate one, and having a correct way to do it is a good idea.
But unless you know the type of 'x', how do you know whether it
has attributes 'i' or 'j'?


If the compiler knows (through declarations, type inference, or
whatever) that x is a certain type of class instance, then it knows
what attributes x has.
Oct 5 '05 #54
Magnus Lycka <ly***@carmen.se> writes:
It seems you've missed the entire point of using a dynamically
typed language. It's not just about saving typing time and making
your methods take up fewer lines of code. It's about writing generic
code. Just look at C++ with all that mess with complex templates,
silly casting and dangerous void pointers etc that are needed to
achieve a fraction of the genericity that Python provides with no
effort from the programmer.


So where are the complex templates and dangerous void pointers in ML?
Oct 5 '05 #55
Op 2005-10-05, Duncan Booth schreef <du**********@invalid.invalid>:
Paul Rubin wrote:
Brian Quinlan <br***@sweetapp.com> writes:
Have those of you who think that the lack of required declarations in
Python is a huge weakness given any thought to the impact that adding
them would have on the rest of the language? I can't imagine how any
language with required declarations could even remotely resemble
Python.


What's the big deal? Perl has an option for flagging undeclared
variables with warnings ("perl -w") or errors ("use strict") and Perl
docs I've seen advise using at least "perl -w" routinely. Those
didn't have much impact. Python already has a "global" declaration;
how does it de-Pythonize the language if there's also a "local"
declaration and an option to flag any variable that's not declared as
one or the other?


The difference is that perl actually needs 'use strict' to be useful for
anything more than trivial scripts. Without 'use strict' you can reference
any variable name without getting an error. Python takes a stricter
approach to begin with by throwing an exception if you reference an
undefined variable.

This only leaves the 'assigning to a different name than the one we
intended' problem which seems to worry some people here, and as has been
explained in great detail it incurs a cost to anyone reading the code for
what most Python users consider to be a very small benefit.


It also is one possibility to implement writable closures.

One could for instace have a 'declare' have the effect that
if on a more inner scope such a declared variable is (re)bound it
will rebind the declared variable instead of binding a local name.

--
Antoon Pardon
Oct 5 '05 #56
James A. Donald wrote:
What can one do to swiftly detect this type of bug?


Unit tests. In my experience the edit - test cycle in
Python is typically roughly as fast as the edit - compile
cycle in e.g. C++, and much faster than the full edit -
compile - link - test cycle in C++.

You do use automated tests for your programs don't you?
Otherwise I think you are sifting out gnats while you
are are swallowing camels.

There are also lint-like tools such as pylint and
pychecker if you think static tests are useful for you.

Here at Carmen, we've actually skipped the unit test
step, and run functional tests at once, using the
Texttest framework--and that fits well with our type
of apps. See http://texttest.carmen.se/
Oct 5 '05 #57
Paul Rubin wrote:
Brian Quinlan <br***@sweetapp.com> writes:
Have those of you who think that the lack of required declarations in
Python is a huge weakness given any thought to the impact that adding
them would have on the rest of the language? I can't imagine how any
language with required declarations could even remotely resemble
Python.

Python already has a "global" declaration;


Which is evaluated at runtime, does not require that the actual global
variable be pre-existing, and does not create the global variable if not
actually assigned. I think that is pretty different than your proposal
semantics.
how does it de-Pythonize the language if there's also a "local"
declaration and an option to flag any variable that's not declared as
one or the other?
Your making this feature "optional" contradicts the subject of this
thread i.e. declarations being necessary. But, continuing with your
declaration thought experiment, how are you planning on actually adding
optional useful type declarations to Python e.g. could you please
rewrite this (trivial) snippet using your proposed syntax/semantics?

from xml.dom import *

def do_add(x, y):
return '%s://%s' % (x, y)

def do_something(node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...
...
There's been a proposal from none other than GvR to add optional
static declarations to Python:

http://www.artima.com/weblogs/viewpost.jsp?thread=85551


A few points:
1. making it work in a reasonable way is an acknowledged hard problem
2. it will still probably not involve doing type checking at
compile-time
3. it would only generate a warning, not an error

Cheers,
Brian
Oct 5 '05 #58
Antoon Pardon wrote:
It also is one possibility to implement writable closures.

One could for instace have a 'declare' have the effect that
if on a more inner scope such a declared variable is (re)bound it
will rebind the declared variable instead of binding a local name.


That is one possibility, but I think that it would be better to use a
keyword at the point of the assigment to indicate assignment to an outer
scope. This fits with the way 'global' works: you declare at (or near) the
assignment that it is going to a global variable, not in some far away part
of the code, so the global nature of the assignment is clearly visible. The
'global' keyword itself would be much improved if it appeared on the same
line as the assignment rather than as a separate declaration.

e.g. something like:

var1 = 0

def f():
var2 = 0

def g():
outer var2 = 1 # Assign to outer variable
global var1 = 1 # Assign to global
Oct 5 '05 #59
Brian Quinlan <br***@sweetapp.com> writes:
Python already has a "global" declaration;
Which is evaluated at runtime, does not require that the actual global
variable be pre-existing, and does not create the global variable if
not actually assigned. I think that is pretty different than your
proposal semantics.


Different how?
Your making this feature "optional" contradicts the subject of this
thread i.e. declarations being necessary.
They're necessary if you enable the option.
But, continuing with your declaration thought experiment, how are
you planning on actually adding optional useful type declarations to
Python e.g. could you please rewrite this (trivial) snippet using
your proposed syntax/semantics?


def do_add(x->str, y->str):
return '%s://%s' % (x, y)

def do_something(node->Node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...
Oct 5 '05 #60
Brian Quinlan wrote:
Paul Rubin wrote:
Brian Quinlan <br***@sweetapp.com> writes:

Have those of you who think that the lack of required declarations in
Python is a huge weakness given any thought to the impact that adding
them would have on the rest of the language? I can't imagine how any
language with required declarations could even remotely resemble
Python.

Python already has a "global" declaration;

Which is evaluated at runtime, does not require that the actual global
variable be pre-existing, and does not create the global variable if not
actually assigned. I think that is pretty different than your proposal
semantics.

I believe that "global" is the one Python statement that isn't actually
executable, and simply conditions the code generated during compilation
(to bytecode).

Hard to see why someone would want to use a global declaration unless
they were intending to assign to it, given the sematnics of access.

[...]

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 5 '05 #61
Op 2005-10-05, Duncan Booth schreef <du**********@invalid.invalid>:
Antoon Pardon wrote:
It also is one possibility to implement writable closures.

One could for instace have a 'declare' have the effect that
if on a more inner scope such a declared variable is (re)bound it
will rebind the declared variable instead of binding a local name.
That is one possibility, but I think that it would be better to use a
keyword at the point of the assigment to indicate assignment to an outer
scope. This fits with the way 'global' works: you declare at (or near) the
assignment that it is going to a global variable, not in some far away part
of the code, so the global nature of the assignment is clearly visible.


As far as I understand people don't like global very much so I don't
expect that a second keyword with the same kind of behaviour has
any chance.
The
'global' keyword itself would be much improved if it appeared on the same
line as the assignment rather than as a separate declaration.

e.g. something like:

var1 = 0

def f():
var2 = 0

def g():
outer var2 = 1 # Assign to outer variable
global var1 = 1 # Assign to global


And what would the following do:

def f():

var = 0

def g():

var = 1

def h():

outer var = 2 * var + 1

h()
print var

g()
print var

f()
Oct 5 '05 #62
Antoon Pardon wrote:
Op 2005-10-04, Ron Adam schreef <rr*@ronadam.com>:
Antoon Pardon wrote:
Op 2005-10-03, Steven D'Aprano schreef <st***@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.

so...

no_new_names # limit any new names
lock_name name # lock a name to it's current object
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.

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.

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.

Finding common use cases where these would make a real difference would
also help.

Cheers,
Ron
Oct 5 '05 #63
Antoon Pardon wrote:
As far as I understand people don't like global very much so I don't
expect that a second keyword with the same kind of behaviour has
any chance.
That's why the behaviour I suggest is different than the current behaviour
of global. Arguments against global (it is the only non-executable
statement in Python & it is confusing because people don't understand the
declaration goes inside the function instead of at global scope) don't
apply.
The
'global' keyword itself would be much improved if it appeared on the
same line as the assignment rather than as a separate declaration.

e.g. something like:

var1 = 0

def f():
var2 = 0

def g():
outer var2 = 1 # Assign to outer variable
global var1 = 1 # Assign to global


And what would the following do:

def f():

var = 0

def g():

var = 1

def h():

outer var = 2 * var + 1

h()
print var

g()
print var

f()

It would follow the principle of least surprise and set the value of var in
g() of course. The variable in f is hidden, and if you didn't mean to hide
it you didn't need to give the two variables the same name.

So the output would be:
3
0

(output verified by using my hack for setting scoped variables:)
-------------------------------
from hack import *
def f():
var = 0

def g():
var = 1

def h():
assign(lambda: var, 2 * var + 1)

h()
print var

g()
print var

f()
-------------------------------
Oct 5 '05 #64
Paul Rubin wrote:
Which is evaluated at runtime, does not require that the actual global
variable be pre-existing, and does not create the global variable if
not actually assigned. I think that is pretty different than your
proposal semantics.

Different how?


Aren't you looking for some of compile-time checking that ensures that
only declared variables are actually used? If so, how does global help?
Your making this feature "optional" contradicts the subject of this
thread i.e. declarations being necessary.


They're necessary if you enable the option.


OK. Would it work on a per-module basis or globally?
def do_add(x->str, y->str):
return '%s://%s' % (x, y)

def do_something(node->Node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...


Wouldn't an error be generated because XML_NAMESPACE is not declared?

And I notice that you are not doing any checking that "namespace" is a
valid attribute of the node object. Aren't the typos class of error that
you are looking to catch just as likely to occur for attributes as
variables?

Cheers,
Brian

Oct 5 '05 #65
Mike Meyer wrote:
(snip)
Antoon, at a guess I'd say that Python is the first time you've
encountered a dynamnic language. Being "horrified" at not having
variable declarations,


Mike, "being horrified" by the (perceived as...) lack of variable
declaration was the OP's reaction, not Antoon's.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 5 '05 #66
Brian Quinlan <br***@sweetapp.com> writes:
Aren't you looking for some of compile-time checking that ensures that
only declared variables are actually used? If so, how does global help?
You'd have to declare any variable global, or declare it local, or it
could be a function name (defined with def) or a function arg (in the
function scope), or maybe you could also declare things like loop
indices. If it wasn't one of the above, the compiler would flag it.
Your making this feature "optional" contradicts the subject of this
thread i.e. declarations being necessary.

They're necessary if you enable the option.


OK. Would it work on a per-module basis or globally?


Whatever perl does. I think that means per-module where the option is
given as "use strict" inside the module.
def do_add(x->str, y->str):
return '%s://%s' % (x, y)
def do_something(node->Node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...


Wouldn't an error be generated because XML_NAMESPACE is not declared?


XML_NAMESPACE would be declared in the xml.dom module and the type
info would carry over through the import.
And I notice that you are not doing any checking that "namespace" is a
valid attribute of the node object. Aren't the typos class of error
that you are looking to catch just as likely to occur for attributes
as variables?


The node object is declared to be a Node instance and if the Node
class definition declares a fixed list of slots, then the compiler
would know the slot names and check them. If the Node class doesn't
declare fixed slots, then they're dynamic and are looked up at runtime
in the usual way.
Oct 5 '05 #67
Paul Rubin wrote:
You'd have to declare any variable global, or declare it local, or it
could be a function name (defined with def) or a function arg (in the
function scope), or maybe you could also declare things like loop
indices. If it wasn't one of the above, the compiler would flag it.
OK. The Python compiler would check that the name is declared but it
would not check that it is defined before use? So this would be acceptable:

def foo():
local x
return x
OK. Would it work on a per-module basis or globally?


Whatever perl does. I think that means per-module where the option is
given as "use strict" inside the module.

def do_add(x->str, y->str):
return '%s://%s' % (x, y)
def do_something(node->Node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...


Wouldn't an error be generated because XML_NAMESPACE is not declared?

XML_NAMESPACE would be declared in the xml.dom module and the type
info would carry over through the import.


Problems:
1. your type checking system is optional and xml.dom does not use it
1a. even if xml.dom did declare the type, what if the type were declared
conditionally e.g.

try:
unicode
except NameError:
XML_NAMESPACE<str> = "..."
else:
XML_NAMESPACE<unicode> = u"..."

2. the compiler does not have access to the names in other modules
anyway

And I notice that you are not doing any checking that "namespace" is a
valid attribute of the node object. Aren't the typos class of error
that you are looking to catch just as likely to occur for attributes
as variables?

The node object is declared to be a Node instance and if the Node
class definition declares a fixed list of slots, then the compiler
would know the slot names and check them.


How would you find the class definition for the Node object at
compile-time? And by "slots" do you mean the existing Python slots
concept or something new?
If the Node class doesn't
declare fixed slots, then they're dynamic and are looked up at runtime
in the usual way.


So only pre-defined slotted attributes would be accessable (if the
object uses slots). So the following would not work:

foo = Foo() # slots defined
foo.my_attribute = 'bar'
print foo.my_attribute

Cheers,
Brian
Oct 5 '05 #68
Paul Rubin wrote:
So where are the complex templates and dangerous void pointers in ML?


You're right about that of course. There aren't any templates or
pointers in COBOL either as far as I know, and COBOL has been used
for lots of real world code (which ML hasn't).

I don't know what your point is though.

Sure, Python could have Perl-like declarations, where you just state
that you intend to use a particular name, but don't declare its type.
I don't see any harm in that.

Type declarations or inferred types would, on the other hand, make
Python considerably less dynamic, and would probably bring the need of
additional featurs such as function overloading etc.
Oct 5 '05 #69
Antoon Pardon <ap*****@forel.vub.ac.be> writes:
They also relieve a burden from the run-time, since all variables
are declared, the runtime doesn't has to check whether or not
a variable is accesible, it knows it is. Not in a dynamic language. Python lets you delete variables at run
time, so the only way to know if a variable exists at a specific
point during the execution of an arbitrary program is to execute the
program to that point.

It is not perfect, that doesn't mean it can't help. How much code
deletes variables.


It's not perfect means it may not help. Depends on the cost of being
wrong - which means we need to see how things would be different if
the code was assuming that a variable existed, and then turned out to
be wrong.

Actually, I'd be interested in knowing how you would improve the
current CPython implementation with knowledge about whether or not a
variable existed. The current implementation just does a dictionary
lookup on the name. The lookup fails if the variable doesn't exist. So
checking on the existence of the variable is a byproduct of finding
the value of the variable. So even if it was perfect, it wouldn't
help.
And if you provide type information with the declaration, more
efficient code can be produced.

Only in a few cases. Type inferencing is a well-understood
technology, and will produce code as efficient as a statically type
language in most cases.

I thought it was more than in a few. Without some type information
from the coder, I don't see how you can infer type from library
code.


There's nothing special about library code. It can be anaylyzed just
like any other code.
I think language matters shouldn't be setlled by personal preferences.

I have to agree with that. For whether or not a feature should be
included, there should either be a solid reason dealing with the
functionality of the language - meaning you should have a set of use
cases showing what a feature enables in the language that couldn't be
done at all, or could only be done clumsily, without the feature.

I think this is too strict. Decorators would IMO never made it.


From the impressions I get here, a lot of people would have been happy
with that result.
I think that a feature that could be helpfull in reduction
errors, should be a candidate even if it has no other merrits.
Yes, but that doesn't mean it should be accepted. Otherwise, every
language would be Eiffel. You have to weigh the cost of a feature
against the benefit you get from it - and different people come to
different conclusions. Which is why different languages provide
different levels of bondage.
Except declarations don't add functionality to the language. They
effect the programing process.

It would be one way to get writable closures in the language.
That is added functionality.


Except just adding declerations doesn't give you that. You have to
change the language so that undeclared variables are looked for up the
scope. And that's the only change you need to get writable variables -
some way to indicate that a variable should be checked for up the
scope. There are more lightweight ways to do that than tagging every
*other* variable. Those have been proposed - and rejected.
And we have conflicting claims about
whether that's a good effect or not, all apparently based on nothing
solider than personal experience. Which means the arguments are just
personal preferences.

Whether the good effect is good enough is certainly open for debate.
But the opponents seem to argue that since it is no absolute guarantee,
it is next to useless. Well I can't agree with that kind of argument
and will argue against it.


You're not reading the opponents arguments carefully enough. The
argument is that the benefit from type declerations is overstated, and
in reality doesn't outweigh the cost of declerations.
Antoon, at a guess I'd say that Python is the first time you've
encountered a dynamnic language. Being "horrified" at not having
variable declarations, which is a standard feature of such languages
dating back to the 1950s, is one such indication.

No I'm not horrified at not having variable declarations. I'm in
general very practical with regard to programming, and use what
features a language offers me. However that doesn't stop me from
thinking: Hey if language X would have feature F from language Y,
that could be helpfull.


I'm sorry - I thought you were the OP, who said he was horrified by
that lack.
Dynamic languages tend to express a much wider range of programming
paradigms than languages that are designed to be statically
compiled. Some of these paradigms do away with - or relegate to the
level of "ugly performance hack" - features that someone only
experienced with something like Pascal would consider
essential. Assignment statements are a good example of that.

I think we should get rid of thinking about a language as
static or dynamic. It is not the language which should determine
a static or dynamic approach, it is the problem you are trying
to solve. And if the coder thinks that a static approach is
best for his problem, why shouldn't he solve it that way.


Except that languages *are* static or dynamic. They have different
features, and different behaviors. Rather than tilting at the windmill
of making a dynamic language suitable for static approaches, it's
better to simply use the appropriate tool for the job. Especially if
those changes make the tool *less* suitable for a dynamic approach.
That a language allows a static approach too, doesn't contradict
that it can work dynamically. Everytime a static feature is
suggested, some dynamic folks react as if the dynamic aspect
of python is in perril.


The problem is that such changes invariably have deep impact that
isn't visible until you examine things carefully knowing you're
dealing with a dynamic language. For instance, just as Python can
delete a variable from a name space at run time, it can add a variable
to some name spaces at run time. So the compiler can't reliably
determine that a variable doesn't exist any more than it can reliably
determine that one does. This means that you can't flag using
undeclared variables in those namespaces at compile time without a
fundamental change in the language.
Given these kinds of differences, prior experience is *not* a valid
reason for thinking that some difference must be wrong. Until you have
experience with the language in question, you can't really decide that
some feature being missing is intolerable. You're in the same position
as the guy who told me that a language without a goto would be
unusable based on his experience with old BASIC, FORTRAN IV and
assembler.

There seems to be some misunderstanding, I don't remember stating that
missing declarations are intolerable, I certainly dont think so. I
wouldn't be programming in python for over five years now if I
thought so. But that doesn't mean having the possibilty to
declare is useless.


Again, I was apparently confusing you and the OP. My apologies.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 5 '05 #70
> This is naive. Testing doesn't guarantee anything. If this is what you
think about testing, then testing gives you a false impression of
security. Maybe we should drop testing.


Typechecking is done by a reduced lamda calculus (System F, which is
ML-Style), whereas testing has the full power of a turing complete
language. So _if_ one has to be dropped, it would certainly be
typechecking.

Additionally, testing gives you the added benefit of actually using your
decelared APIs - which serves documentation purposes as well as
securing your design decisions, as you might discover bad design while
actually writing testcases.

Besides that, the false warm feeling of security a successful
compilation run has given many developers made them check untested and
actually broken code into the VCS. I've seen that _very_ often! And the
_only_ thinng that prevents us from doing so is to enforce tests. But
these are more naturally done in python (or similar languages) as every
programmer knows "unless the program run sucsessfully, I can't say
anything about it" than in a statically typed language where the
programmer argues "hey, it compiled, it should work!"
Regards,

Diez
Oct 5 '05 #71
Brian Quinlan <br***@sweetapp.com> writes:
OK. The Python compiler would check that the name is declared but it
would not check that it is defined before use? So this would be
acceptable:

def foo():
local x
return x
Come on, you are asking silly questions. Any reasonable C compiler
would flag something like that and Python (with the flag set) should
do the same. If you want to ask substantive questions, that's fine,
but stop wasting our time with silly stuff.
XML_NAMESPACE would be declared in the xml.dom module and the type
info would carry over through the import.


1. your type checking system is optional and xml.dom does not use it


If type checking is implemented then the stdlib should be updated to
add declarations for public symbols. If not, the compiler would flag
the undeclared symbol. You could always declare it to be of type 'object'.
try:
unicode
except NameError:
XML_NAMESPACE<str> = "..."
else:
XML_NAMESPACE<unicode> = u"..."
This wouldn't be allowed.
2. the compiler does not have access to the names in other modules anyway
You're being silly again. The compiler would examine the other module
when it processes the import statement, just like it does now.
How would you find the class definition for the Node object at
compile-time?
By processing the xml.dom module when it's imported.
And by "slots" do you mean the existing Python slots concept or
something new?
Probably something new, if the existing concept is incompatible in some way.
So only pre-defined slotted attributes would be accessable (if the
object uses slots). So the following would not work:

foo = Foo() # slots defined
foo.my_attribute = 'bar'
print foo.my_attribute


Yes, correct, many people already think the existing __slots__
variable is intended for precisely that purpose and try to use it that
way. Note you can get the same effect with a suitable __setattr__
method that's activated after __init__ returns, so all we're
discussing is a way to make the equivalent more convenient.
Oct 5 '05 #72
On 5 Oct 2005 09:27:04 GMT, Duncan Booth <du**********@invalid.invalid> wrote:
Antoon Pardon wrote:
It also is one possibility to implement writable closures.

One could for instace have a 'declare' have the effect that
if on a more inner scope such a declared variable is (re)bound it
will rebind the declared variable instead of binding a local name.


That is one possibility, but I think that it would be better to use a
keyword at the point of the assigment to indicate assignment to an outer
scope. This fits with the way 'global' works: you declare at (or near) the
assignment that it is going to a global variable, not in some far away part
of the code, so the global nature of the assignment is clearly visible. The
'global' keyword itself would be much improved if it appeared on the same
line as the assignment rather than as a separate declaration.

e.g. something like:

var1 = 0

def f():
var2 = 0

def g():
outer var2 = 1 # Assign to outer variable
global var1 = 1 # Assign to global


IMO you don't really need all that cruft most of the time. E.g., what if ':='
meant 'assign to variable wherever it is (and it must exist), searching according
to normal variable resolution order (fresh coinage, vro for short ;-), starting with
local, then lexically enclosing and so forth out to module global (but not to builtins).'

If you wanted to assign/rebind past a local var shadowing an enclosing variable var, you'd have
to use e.g. vro(1).var = expr instead of var := expr. Sort of analogous to
type(self).mro()[1].method(self, ...) Hm, vro(1).__dict__['var'] = expr could conceivably
force binding at the vro(1) scope specifically, and not search outwards. But for that there
would be optimization issues I think, since allowing an arbitrary binding would force a real
dict creation on the fly to hold the the new name slot.

BTW, if/when we can push a new namespace on top of the vro stack with a 'with namespace: ...' or such,
vro(0) would still be at the top, and vro(1) will be the local before the with, and := can still
be sugar for find-and-rebind.

Using := and not finding something to rebind would be a NameError. Ditto for
vro(n).nonexistent_name_at_level_n_or_outwards. vro(-1) could refer global module scope
and vro(-2) go inwards towards local scope at vro(0). So vro(-1).gvar=expr would
give you the effect of globals()['gvar']=expr with a pre-existence check.

The pre-existence requirement would effectively be a kind of declaration requirement for
the var := expr usage, and an initialization to a particular type could enhance inference.
Especially if you could have a decorator for statements in general, not just def's, and
you could then have a sticky-types decoration that would say certain bindings may be inferred
to stick to their initial binding's object's type.

Rambling uncontrollably ;-)
My .02USD ;-)

Regards,
Bengt Richter
Oct 6 '05 #73
Op 2005-10-06, Bengt Richter schreef <bo**@oz.net>:
On 5 Oct 2005 09:27:04 GMT, Duncan Booth <du**********@invalid.invalid> wrote:
Antoon Pardon wrote:
It also is one possibility to implement writable closures.

One could for instace have a 'declare' have the effect that
if on a more inner scope such a declared variable is (re)bound it
will rebind the declared variable instead of binding a local name.


That is one possibility, but I think that it would be better to use a
keyword at the point of the assigment to indicate assignment to an outer
scope. This fits with the way 'global' works: you declare at (or near) the
assignment that it is going to a global variable, not in some far away part
of the code, so the global nature of the assignment is clearly visible. The
'global' keyword itself would be much improved if it appeared on the same
line as the assignment rather than as a separate declaration.

e.g. something like:

var1 = 0

def f():
var2 = 0

def g():
outer var2 = 1 # Assign to outer variable
global var1 = 1 # Assign to global


IMO you don't really need all that cruft most of the time. E.g., what if ':='
meant 'assign to variable wherever it is (and it must exist), searching according
to normal variable resolution order (fresh coinage, vro for short ;-), starting with
local, then lexically enclosing and so forth out to module global (but not to builtins).'


Just some ideas about this

1) Would it be usefull to make ':=' an expression instead if a
statement?

I think the most important reason that the assignment is a statement
and not an expression would apply less here because '==' is less easy
to turn into ':=' by mistake than into =

Even if people though that kind of bug was still too easy

2) What if we reversed the operation. Instead of var := expression,
we write expression =: var.

IMO this would make it almost impossible to write an assignment
by mistake in a conditional when you meant to test for equality.

--
Antoon Pardon
Oct 6 '05 #74
Op 2005-10-05, Brian Quinlan schreef <br***@sweetapp.com>:
Paul Rubin wrote:
Brian Quinlan <br***@sweetapp.com> writes:
Have those of you who think that the lack of required declarations in
Python is a huge weakness given any thought to the impact that adding
them would have on the rest of the language? I can't imagine how any
language with required declarations could even remotely resemble
Python.

Python already has a "global" declaration;


Which is evaluated at runtime, does not require that the actual global
variable be pre-existing, and does not create the global variable if not
actually assigned. I think that is pretty different than your proposal
semantics.
how does it de-Pythonize the language if there's also a "local"
declaration and an option to flag any variable that's not declared as
one or the other?


Your making this feature "optional" contradicts the subject of this
thread i.e. declarations being necessary. But, continuing with your
declaration thought experiment, how are you planning on actually adding
optional useful type declarations to Python e.g. could you please
rewrite this (trivial) snippet using your proposed syntax/semantics?

from xml.dom import *

def do_add(x, y):
return '%s://%s' % (x, y)

def do_something(node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...
...


IMO your variable are already mostly declared. The x and y in
the do_add is kind of a declarartion for the parameters x and
y.

--
Antoon Pardon
Oct 6 '05 #75
On Wed, 05 Oct 2005 11:10:58 GMT, Ron Adam <rr*@ronadam.com> wrote:
Antoon Pardon wrote:
Op 2005-10-04, Ron Adam schreef <rr*@ronadam.com>:
Antoon Pardon wrote:

Op 2005-10-03, Steven D'Aprano schreef <st***@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
Oct 6 '05 #76
Op 2005-10-05, Mike Meyer schreef <mw*@mired.org>:
Antoon Pardon <ap*****@forel.vub.ac.be> writes:
They also relieve a burden from the run-time, since all variables
are declared, the runtime doesn't has to check whether or not
a variable is accesible, it knows it is.
Not in a dynamic language. Python lets you delete variables at run
time, so the only way to know if a variable exists at a specific
point during the execution of an arbitrary program is to execute the
program to that point. It is not perfect, that doesn't mean it can't help. How much code
deletes variables.


It's not perfect means it may not help. Depends on the cost of being
wrong - which means we need to see how things would be different if
the code was assuming that a variable existed, and then turned out to
be wrong.

Actually, I'd be interested in knowing how you would improve the
current CPython implementation with knowledge about whether or not a
variable existed. The current implementation just does a dictionary
lookup on the name. The lookup fails if the variable doesn't exist. So
checking on the existence of the variable is a byproduct of finding
the value of the variable. So even if it was perfect, it wouldn't
help.


Yes it would. A function with a declare statement could work
as the __slots__ attribute in a class. AFAIU each variable
would then internally be associated with a number and the
dictionary would be replace by a list. Finding the value
of the variable would just be indexing this table.
And if you provide type information with the declaration, more
efficient code can be produced.
Only in a few cases. Type inferencing is a well-understood
technology, and will produce code as efficient as a statically type
language in most cases.

I thought it was more than in a few. Without some type information
from the coder, I don't see how you can infer type from library
code.


There's nothing special about library code. It can be anaylyzed just
like any other code.


Not necessarily, library code may not come with source, so there
is little to be analyzed then.
Except declarations don't add functionality to the language. They
effect the programing process.

It would be one way to get writable closures in the language.
That is added functionality.


Except just adding declerations doesn't give you that. You have to
change the language so that undeclared variables are looked for up the
scope.


They already are. The only exception being when the variable is
(re)bound. This can give you 'surprising' results like the
following.

a = []
b = []
def f():
a[:] = range(10)
b = range(10)

f()
print a
print b

which will gibe the following result.

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[]

And we have conflicting claims about
whether that's a good effect or not, all apparently based on nothing
solider than personal experience. Which means the arguments are just
personal preferences.

Whether the good effect is good enough is certainly open for debate.
But the opponents seem to argue that since it is no absolute guarantee,
it is next to useless. Well I can't agree with that kind of argument
and will argue against it.


You're not reading the opponents arguments carefully enough. The
argument is that the benefit from type declerations is overstated, and
in reality doesn't outweigh the cost of declerations.


That may be there intend, but often enough I see arguments that boil
down to the fact that declarations won't solve a particular problem
completely as if that settles it.
Dynamic languages tend to express a much wider range of programming
paradigms than languages that are designed to be statically
compiled. Some of these paradigms do away with - or relegate to the
level of "ugly performance hack" - features that someone only
experienced with something like Pascal would consider
essential. Assignment statements are a good example of that.

I think we should get rid of thinking about a language as
static or dynamic. It is not the language which should determine
a static or dynamic approach, it is the problem you are trying
to solve. And if the coder thinks that a static approach is
best for his problem, why shouldn't he solve it that way.


Except that languages *are* static or dynamic.


Not in the way a lot of people seem to think here. Adding declarations
doesn't need to take away any dynamism from the language.
They have different
features, and different behaviors. Rather than tilting at the windmill
of making a dynamic language suitable for static approaches, it's
better to simply use the appropriate tool for the job. Especially if
those changes make the tool *less* suitable for a dynamic approach.


They don't. That seems to be the big fear after a lot of resistance
but IMO it is unfounded.

If I write a module that only makes sense with floating point numbers,
declaring those variables as floats and allowing the compiler to
generate code optimised for floating point numbers, will in no
way restrict any one else from using the full dynamic features of
the language.
That a language allows a static approach too, doesn't contradict
that it can work dynamically. Everytime a static feature is
suggested, some dynamic folks react as if the dynamic aspect
of python is in perril.


The problem is that such changes invariably have deep impact that
isn't visible until you examine things carefully knowing you're
dealing with a dynamic language. For instance, just as Python can
delete a variable from a name space at run time, it can add a variable
to some name spaces at run time. So the compiler can't reliably
determine that a variable doesn't exist any more than it can reliably
determine that one does. This means that you can't flag using
undeclared variables in those namespaces at compile time without a
fundamental change in the language.


Yes it can. AFAIK python doesn't allow that a variable is created
in a function scope from somewhere else. Sure it may be possible
through some hack that works in the current C implemantation,
but there is a difference between what the language allows and
what is possible in a specific implementation.

Python also has the __slots__ attribute which prohibites attributes
to be added or deleted from instances.

Python can work with C-extension. What would have been the difference
if python would have had a number of static features that would have
allowed this kind of code be written in python itself. Look at pyrex,
I don't see where it lacks in dynamism with respect to python.

--
Antoon Pardon
Oct 6 '05 #77
Op 2005-10-05, Diez B. Roggisch schreef <de***@nospam.web.de>:
This is naive. Testing doesn't guarantee anything. If this is what you
think about testing, then testing gives you a false impression of
security. Maybe we should drop testing.
Typechecking is done by a reduced lamda calculus (System F, which is
ML-Style), whereas testing has the full power of a turing complete
language. So _if_ one has to be dropped, it would certainly be
typechecking.


Sure, But allow me this silly analogy.

Going out on a full test-drive will also reveal your tires are flat.
So if you one has to be dropped, a full test drive or a tire check
it would certainly be the tired check. But IMO the tire check
is still usefull.
Additionally, testing gives you the added benefit of actually using your
decelared APIs - which serves documentation purposes as well as
securing your design decisions, as you might discover bad design while
actually writing testcases.
Hey, I'm all for testing. I never suggested testing should be dropped
for declarations
Besides that, the false warm feeling of security a successful
compilation run has given many developers made them check untested and
actually broken code into the VCS. I've seen that _very_ often! And the
_only_ thinng that prevents us from doing so is to enforce tests.
I wonder how experienced are these programmers? I know I had this
feeling when I started at the univeristy, but before I left I
already wrote my programs in rather small pieces that were tested
before moving on.
But
these are more naturally done in python (or similar languages) as every
programmer knows "unless the program run sucsessfully, I can't say
anything about it" than in a statically typed language where the
programmer argues "hey, it compiled, it should work!"


Again I do have to wonder about how experienced these programmers are.

--
Antoon Pardon
Oct 6 '05 #78
Antoon Pardon wrote:
from xml.dom import *

def do_add(x, y):
return '%s://%s' % (x, y)

def do_something(node):
if node.namespace == XML_NAMESPACE:
return do_add('http://', node.namespace)
elif node.namespace == ...
...


IMO your variable are already mostly declared. The x and y in
the do_add is kind of a declarartion for the parameters x and
y.


I think you missed his point, though I'm not surprised since unless you
are familiar with the internals of the xml package it isn't obvious just
how complex this situation is.

The value XML_NAMESPACE was imported from xml.dom, but the xml package is
kind of weird. XML_NAMESPACE defined both in xml.dom and in the
_xmlplus.dom package. The _xmlplus package is conditionally imported by the
xml package, and completely replaces it, but only if _xmlplus is present
and at least version 0.8.4 (older versions are ignored).

This is precisely the kind of flexibility which gives Python a lot of its
power, but it means that you cannot tell without running the code which
package actually provides xml.dom.

Of course, I would expect that if you enforced strict variable declarations
you would also disallow 'from x import *', but you still cannot tell until
runtime whether an particular module will supply a particular variable, not
what type it is.
Oct 6 '05 #79
Paul Rubin wrote:
Brian Quinlan <br***@sweetapp.com> writes:
OK. The Python compiler would check that the name is declared but it
would not check that it is defined before use? So this would be
acceptable:

def foo():
local x
return x

Come on, you are asking silly questions. Any reasonable C compiler
would flag something like that and Python (with the flag set) should
do the same. If you want to ask substantive questions, that's fine,
but stop wasting our time with silly stuff.


I'm not trying to be silly. I am trying to get a handle on the semantics
that you are proposing. So we now have two requirements for the new
declaration syntax (please let me know if I'm wrong):

o the variable must be declared
o the variable must be assigned

I would assume that you would make it so that assignment and delaration
happen as part of the same statement?
If type checking is implemented then the stdlib should be updated to
add declarations for public symbols. If not, the compiler would flag
the undeclared symbol. You could always declare it to be of type 'object'.
Fair enough.
try:
unicode
except NameError:
XML_NAMESPACE<str> = "..."
else:
XML_NAMESPACE<unicode> = u"..."

This wouldn't be allowed.


OK, that sucks.
2. the compiler does not have access to the names in other modules anyway

You're being silly again. The compiler would examine the other module
when it processes the import statement, just like it does now.


Right now, the compiler DOES NOT examine the contents of the other
modules. All it does is generate an IMPORT_NAME instruction which is
evaluation during runtime. So are you proposing that the compiler now
scan other modules during compilation?
How would you find the class definition for the Node object at
compile-time?

By processing the xml.dom module when it's imported.


Import happens at runtime (see above). But you seem to want compile-time
type checking.

Cheers,
Brian
Oct 6 '05 #80
Duncan Booth <du**********@invalid.invalid> writes:
The value XML_NAMESPACE was imported from xml.dom, but the xml package is
kind of weird. XML_NAMESPACE defined both in xml.dom and in the
_xmlplus.dom package. The _xmlplus package is conditionally imported by the
xml package, and completely replaces it, but only if _xmlplus is present
and at least version 0.8.4 (older versions are ignored).

This is precisely the kind of flexibility which gives Python a lot of its
power, but it means that you cannot tell without running the code which
package actually provides xml.dom.


This sounds like the socket module, which is a total mess. Library
code should not be written like that.
Oct 6 '05 #81
Brian Quinlan <br***@sweetapp.com> writes:
I'm not trying to be silly. I am trying to get a handle on the
semantics that you are proposing. So we now have two requirements for
the new declaration syntax (please let me know if I'm wrong):

o the variable must be declared
o the variable must be assigned
These would both be errors that the compiler could and should check
for, if declaration checking is enabled. However, they would not be
syntax errors.
I would assume that you would make it so that assignment and
delaration happen as part of the same statement?
Sure, why not.
Right now, the compiler DOES NOT examine the contents of the other
modules. All it does is generate an IMPORT_NAME instruction which is
evaluation during runtime.
In that case the other module gets compiled when the IMPORT_NAME
instruction is executed. That says that compile time and runtime are
really the same thing in the current system.
So are you proposing that the compiler now scan other modules during
compilation?


Yeah, maybe some optimization is possible.
Oct 6 '05 #82
> Sure, But allow me this silly analogy.

Going out on a full test-drive will also reveal your tires are flat.
So if you one has to be dropped, a full test drive or a tire check
it would certainly be the tired check. But IMO the tire check
is still usefull.
But you could write it as test - including not only a look (which
resembles the limited capabilities of typechecking), but testing the air
pressure, looking at the tyre type and see that it won't match the rainy
conditions...
Hey, I'm all for testing. I never suggested testing should be dropped
for declarations
The testing is IMHO more valuable than typechecking. The latter one
actually _limits_ me. See e.g. the java IO-Api for a very bloated way of
what comes very naturally with python. Duck-typing at it's best. The
only reason I see typechecking is good for is optimization. But that is
not the problem with JAVA/.NET anyway. And could possibly be done with
psyco.
I wonder how experienced are these programmers? I know I had this
feeling when I started at the univeristy, but before I left I
already wrote my programs in rather small pieces that were tested
before moving on.
<snip>
Again I do have to wonder about how experienced these programmers are.


Well - surely they aren't. But that is beyond your control - you can't
just stomp into a company and declare your own superiority and force
others your way. I was astonished to hear that even MS just recently
adopted test-driven development for their upcoming windows vista. And
they are commonly seen as sort of whiz-kid hiring hi-class company,
certified CMM Levelo 6 and so on....

The discussion is somewhat moot - typechecking is not nonsense. But
matter of factly, _no_ programm runs without testing. And developing a
good testing culture is cruicial. Where OTH a lot of large and
successful projects exist (namely the python ones, amongst others..)
that show that testing alone without typechecking seems to be good enough.

Diez
Oct 6 '05 #83
Op 2005-10-06, Diez B. Roggisch schreef <de***@nospam.web.de>:
Sure, But allow me this silly analogy.

Going out on a full test-drive will also reveal your tires are flat.
So if you one has to be dropped, a full test drive or a tire check
it would certainly be the tired check. But IMO the tire check
is still usefull.


But you could write it as test - including not only a look (which
resembles the limited capabilities of typechecking), but testing the air
pressure, looking at the tyre type and see that it won't match the rainy
conditions...
Hey, I'm all for testing. I never suggested testing should be dropped
for declarations


The testing is IMHO more valuable than typechecking. The latter one
actually _limits_ me. See e.g. the java IO-Api for a very bloated way of
what comes very naturally with python. Duck-typing at it's best.


But typechecking doesn't has to be java like.

I can't help but feel that a lot of people have specific typechecking
systems in mind and then conclude that the limits of such a symtem
are inherent in typechecking itself.

IMO a good type system doesn't need to limit python in any way.

--
Antoon Pardon
Oct 6 '05 #84
>
I can't help but feel that a lot of people have specific typechecking
systems in mind and then conclude that the limits of such a symtem
are inherent in typechecking itself.
I've been writing a type-checker for my diploma thesis for a functionnal
programmming language. And it _is_ limited. The very subject of my work
was to explore extended type-checking methods (so called
multi-level-specifications),, which can be shwon to be NP-hard problems.
Which naturally limits the domains they can be used to.
IMO a good type system doesn't need to limit python in any way.


It has to. certainly. Take alone the list implementation - while
typesystems as ML allow for generics (with much less typing overhead
than JAVA), the list is always homogenous. Which python's aren't - and
that a great thing(tm), even though ususally the contents of a list
share some common behaviour. And that exactly is the key point here: in
a statically typed world, that common behaviour must have been extracted
and made explicit. Which is the cause for that notorious java io API.
And, to extend the argument to ML-type type-checking, there you need a
disjoint union of the possible types - _beforehand_, and the code
dealing with it has to be aware of it.

In python OTH, I just pass objects I like into the list - if they
behave, fine.

DIez
Oct 6 '05 #85
Op 2005-10-06, Diez B. Roggisch schreef <de***@nospam.web.de>:

I can't help but feel that a lot of people have specific typechecking
systems in mind and then conclude that the limits of such a symtem
are inherent in typechecking itself.
I've been writing a type-checker for my diploma thesis for a functionnal
programmming language. And it _is_ limited. The very subject of my work
was to explore extended type-checking methods (so called
multi-level-specifications),, which can be shwon to be NP-hard problems.
Which naturally limits the domains they can be used to.
IMO a good type system doesn't need to limit python in any way.


It has to. certainly. Take alone the list implementation - while
typesystems as ML allow for generics (with much less typing overhead
than JAVA), the list is always homogenous. Which python's aren't - and
that a great thing(tm),


Suppose we have a typesystem which has the type ANY, which would mean
such an object could be any type. You could then have homogenous lists
in the sense that all elements should be of the same declared type and
at the same time mix all kind of type in a particular list, just
as python does.

So how would this limit python.
even though ususally the contents of a list
share some common behaviour. And that exactly is the key point here: in
a statically typed world, that common behaviour must have been extracted
and made explicit.
Would my suggestion be classified as a statically typed world?
Which is the cause for that notorious java io API.
And, to extend the argument to ML-type type-checking, there you need a
disjoint union of the possible types - _beforehand_, and the code
dealing with it has to be aware of it.

In python OTH, I just pass objects I like into the list - if they
behave, fine.


But now we are no longer talking about how typechecking would limit
the language but about convenience for the user.

--
Antoon Pardon
Oct 6 '05 #86
> Suppose we have a typesystem which has the type ANY, which would mean
such an object could be any type. You could then have homogenous lists
in the sense that all elements should be of the same declared type and
at the same time mix all kind of type in a particular list, just
as python does.
The you have JAVA Object or C void*. Which cause all kinds of runtime
troubles.... because they essentially circumvene the typechecking!

So how would this limit python.
The limitation is that in static languages I must _know_ what type to
cast such an ANY, before calling anything on it. Otherwise its useless.
even though ususally the contents of a list
share some common behaviour. And that exactly is the key point here: in
a statically typed world, that common behaviour must have been extracted
and made explicit.

Would my suggestion be classified as a statically typed world?


See above.

Which is the cause for that notorious java io API.
And, to extend the argument to ML-type type-checking, there you need a
disjoint union of the possible types - _beforehand_, and the code
dealing with it has to be aware of it.

In python OTH, I just pass objects I like into the list - if they
behave, fine.

But now we are no longer talking about how typechecking would limit
the language but about convenience for the user.


That's dialectics. Limits in the language limit the user and make things
inconvenient.

Diez
Oct 6 '05 #87
Mike Meyer a écrit :
Antoon Pardon <ap*****@forel.vub.ac.be> writes:
Op 2005-10-03, Steven D'Aprano schreef <st***@REMOVETHIScyber.com.au>:
On Mon, 03 Oct 2005 13:58:33 +0000, Antoon Pardon wrote:
Declarations also allow easier writable closures. Since the declaration
happens at a certain scope, the run time can easily find the correct
scope when a variable is rebound.

If it happens at runtime, then you can do it without declarations:
they're gone by then. Come to think of it, most functional languages -
which are the languages that make the heaviest use of closures - don't
require variable declarations.


Well, can you give a single example of such language ? Because all the
functionnal language I know but one do need variable declaration : lisp,
scheme, ocaml, haskell do need variable declaration ! Erlang do not ...

[...]

Only in a few cases. Type inferencing is a well-understood
technology, and will produce code as efficient as a statically type
language in most cases.

Type inferencing only works for statically typed languages AFAIK ! In a
dynamically typed languages, typing a variable is simply impossible as
any function may return a value of any type !
I think language matters shouldn't be setlled by personal preferences.

I have to agree with that. For whether or not a feature should be
included, there should either be a solid reason dealing with the
functionality of the language - meaning you should have a set of use
cases showing what a feature enables in the language that couldn't be
done at all, or could only be done clumsily, without the feature.


Wrong argument ... with that kind of things, you would just stick with
plain Turing machine ... every single computation can be done with it !

Except declarations don't add functionality to the language. They
effect the programing process. And we have conflicting claims about
whether that's a good effect or not, all apparently based on nothing
solider than personal experience. Which means the arguments are just
personal preferences.

Well, so why not *allow* for variable declaration ? Languages like Perl
does that successfully ... you don't like : you don't do ! you like :
you do ! A simple option at the beginning of the file tell the compilor
if variable declaration is mandatory or not !
Until someone does the research to provide hard evidence one way or
another, that's all we've got to work with. Which means that languages
should exist both with and with those features, and if one sides
experiences generalize to the population at large, they alternative
languages will die out. Which hasn't happened yet.

But we should decide what language features are usefull and which are
not by what some individual can or can't live without.

Um - that's just personal preference (though I may have misparsed your
sentence). What one person can't live without, another may not be able
to live with. All that means is that they aren't likely to be happy
with the same programming language. Which is fine - just as no
programming language can do everything, no programming language can
please everyone.

Antoon, at a guess I'd say that Python is the first time you've
encountered a dynamnic language. Being "horrified" at not having
variable declarations, which is a standard feature of such languages
dating back to the 1950s, is one such indication.


Dynamic language and variable declaration are non-related issues ! You
can have statically-typed language without variable declaration (i.e.
BASIC) and dynamically-typed language with (i.e. Lisp) ! Please, when
you says something about languages, at least give 1 name of language
asserting what you're saying !
Dynamic languages tend to express a much wider range of programming
paradigms than languages that are designed to be statically
compiled. Some of these paradigms do away with - or relegate to the
level of "ugly performance hack" - features that someone only
experienced with something like Pascal would consider
essential. Assignment statements are a good example of that.
Well, could you be more specific once more ? I can't that many paradigm
only available on dynamically typed languages ... beside duck-typing
(which is basically a synonym for dynamically-typed)
Given these kinds of differences, prior experience is *not* a valid
reason for thinking that some difference must be wrong. Until you have
experience with the language in question, you can't really decide that
some feature being missing is intolerable. You're in the same position
as the guy who told me that a language without a goto would be
unusable based on his experience with old BASIC, FORTRAN IV and
assembler.
After more than two years of Python programming, I still fill the need
for variable declarations. It would remove tons of bugs for little works
and would also clarify the scope of any single variable.
Pick one of the many languages that don't require declarations. Try
writing a code in them, and see how much of a problem it really is in
practice, rather than trying to predict that without any
information. Be warned that there are *lots* of variations on how
undeclared variables are treated when referenced. Python raises
exceptions. Rexx gives them their print name as a value. Other
languages do other things.

<mike


Well, IMO, worst case is silently give a default value, like PHP (or
apparently Rexx) does ... this can hide bugs for month if a single
test-case is missing !

Well, in the end, I would really like an *option* at the beginning of a
module file requiring variable declaration for the module. It would
satisfy both the ones who want and the ones who don't want that ...

Pierre
Oct 6 '05 #88
Pierre Barbier de Reuille <pi************@cirad.fr> writes:
Mike Meyer a écrit :
Antoon Pardon <ap*****@forel.vub.ac.be> writes:
Op 2005-10-03, Steven D'Aprano schreef <st***@REMOVETHIScyber.com.au>:

On Mon, 03 Oct 2005 13:58:33 +0000, Antoon Pardon wrote:

Declarations also allow easier writable closures. Since the declaration
happens at a certain scope, the run time can easily find the correct
scope when a variable is rebound.

If it happens at runtime, then you can do it without declarations:
they're gone by then. Come to think of it, most functional languages -
which are the languages that make the heaviest use of closures - don't
require variable declarations.

Well, can you give a single example of such language ? Because all the
functionnal language I know but one do need variable declaration : lisp,
scheme, ocaml, haskell do need variable declaration ! Erlang do not ...


Scheme and lisp don't need variable declerations. Last time I looked,
Schemd didn't even *allow* variable declerations.
Only in a few cases. Type inferencing is a well-understood
technology, and will produce code as efficient as a statically type
language in most cases.

Type inferencing only works for statically typed languages AFAIK ! In a
dynamically typed languages, typing a variable is simply impossible as
any function may return a value of any type !


I think we're using different definitions of statically typed
here. A language that is statically typed doesn't *need* type
inferencing - the types are all declared! Type determines the thypes
by inferenceing them from an examination of the program. So, for
instance, it can determine that this function:

def foo():
return 1

Won't ever return anything but an integer.
I think language matters shouldn't be setlled by personal preferences.

I have to agree with that. For whether or not a feature should be
included, there should either be a solid reason dealing with the
functionality of the language - meaning you should have a set of use
cases showing what a feature enables in the language that couldn't be
done at all, or could only be done clumsily, without the feature.

Wrong argument ... with that kind of things, you would just stick with
plain Turing machine ... every single computation can be done with it !


"Computation" is is not the same thing as "Functionality". If you
think otherwise, show me how to declare an object with a Turing
machine.

And there's also the issue of "clumsily". Turing machines are clumsy
to program in.

Except declarations don't add functionality to the language. They
effect the programing process. And we have conflicting claims about
whether that's a good effect or not, all apparently based on nothing
solider than personal experience. Which means the arguments are just
personal preferences.

Well, so why not *allow* for variable declaration ? Languages like Perl
does that successfully ... you don't like : you don't do ! you like :
you do ! A simple option at the beginning of the file tell the compilor
if variable declaration is mandatory or not !


Perl is a red herring. Unless it's changed radically since I last
looked, undeclared variables in Perl have dynamic scope, not lexical
scope. While dynamically scoped variables are a powerful feature, and
there have been proposals to add them to Python, having them be the
default is just *wrong*. If I were writing in Perl, I'd want
everything declared just to avoid that. Of course, if Python behaved
that way, I'd do what I did with Perl, and change languages.
Antoon, at a guess I'd say that Python is the first time you've
encountered a dynamnic language. Being "horrified" at not having
variable declarations, which is a standard feature of such languages
dating back to the 1950s, is one such indication.

Dynamic language and variable declaration are non-related issues ! You
can have statically-typed language without variable declaration (i.e.
BASIC) and dynamically-typed language with (i.e. Lisp) ! Please, when
you says something about languages, at least give 1 name of language
asserting what you're saying !


Declerations and typing are *also* non-related issues. See Perl. Also
see the subject line.
Dynamic languages tend to express a much wider range of programming
paradigms than languages that are designed to be statically
compiled. Some of these paradigms do away with - or relegate to the
level of "ugly performance hack" - features that someone only
experienced with something like Pascal would consider
essential. Assignment statements are a good example of that.

Well, could you be more specific once more ? I can't that many paradigm
only available on dynamically typed languages ... beside duck-typing
(which is basically a synonym for dynamically-typed)


I said "dynamic languages", *not* "dynamically typed languages". They
aren't the same thing. Dynamic languages let you create new functions,
variables and attributes at run time. Python lets you delete them as
well. This means that simle declarations can't tell you whether or
not a variable will exist at runtime, because it may have been added
at run time.
Given these kinds of differences, prior experience is *not* a valid
reason for thinking that some difference must be wrong. Until you have
experience with the language in question, you can't really decide that
some feature being missing is intolerable. You're in the same position
as the guy who told me that a language without a goto would be
unusable based on his experience with old BASIC, FORTRAN IV and
assembler.

After more than two years of Python programming, I still fill the need
for variable declarations. It would remove tons of bugs for little works
and would also clarify the scope of any single variable.


Maybe you're still writing code for a language with declerations? I
never felt that need. Then again, I came to Python from a language
that didn't require declerations: Scheme.
Pick one of the many languages that don't require declarations. Try
writing a code in them, and see how much of a problem it really is in
practice, rather than trying to predict that without any
information. Be warned that there are *lots* of variations on how
undeclared variables are treated when referenced. Python raises
exceptions. Rexx gives them their print name as a value. Other
languages do other things.

Well, IMO, worst case is silently give a default value, like PHP (or
apparently Rexx) does ... this can hide bugs for month if a single
test-case is missing !

Well, in the end, I would really like an *option* at the beginning of a
module file requiring variable declaration for the module. It would
satisfy both the ones who want and the ones who don't want that ...


Nope. It would just change the argument from "Python should have ..."
to "You should always use ..." or "Module foo should use ...".

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 6 '05 #89
Bengt Richter wrote:
On Wed, 05 Oct 2005 11:10:58 GMT, Ron Adam <rr*@ronadam.com> wrote:

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.,


Works for me.

__lock_names__ = True

It's not too different than __name__ == '__main__'...

>>> 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'


Hmm... To make it work this way, the globals and arguments need to have
local references.

@nnn
def few(x,y):
global range
range = range
x,y = x,y
a = 'a'
b = 'b'
i = j = k = l = None
L = 1
__no_new_names__ = True
L += 1
for i in range(x,y):
print I
>>> @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 ;-)


I had the thought that collecting the names from the 'STORE FAST' lines
of dis.dis(f) would work nicely, but... dis.dis() doesn't return a
string like I expected, but prints the output as it goes. This seems
like it would be easy to fix and it would make the dis module more
useful. I'd like to be able to do...

D = dis.dis(f)

An alternate option to output the disassembly to a list of of tuples.
That would make analyzing the output really easy. ;-)

Something like...

good_names = []
nnnames = False
for line in dis.dislist(f):
if line[2] = 'SAVE_FAST':
if not nnnames:
if line[-1] = '(__no_new_names__)':
nnnames=True
continue
good_names.append(line[-1])
else:
assert line[-1]in good_names, 'Bad name:%r'% line[-1]

So, I wonder what kind of errors can be found by analyzing the disassembly?

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


Using dis.dis it becomes two sequential 'STORE_FAST' operations. So add
(x) to the don't change list, and catch it on the next 'STORE_FAST' for
(x). ;-)

28 12 LOAD_GLOBAL 2 (True)
15 DUP_TOP
16 STORE_FAST 0 (x)
19 STORE_FAST 8 (__lock_name__)

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.


That was more or less what I had in mind, but I think keeping things as
passive as possible is what is needed. One thought is to use this type
of thing along with __debug__.

if __debug__: __nnn__ = True
Wouldn't a debug block or suite be better than an if __debug__:? Just a
thought. Even if the -0 option is given the if __debug__: check is
still there. Which means you still need to comment it out if it's in an
inner loop.

debug: __nnn__ = True # Is not included if __debug__ is false.

or...

MAX = 256
MIN = 0
debug:
__lock__ = MIN, MAX # helps checker app
__no_new_names__ = True # find bugs.

for MAX in range(1000): # If __debug__, checker app catches
this.
if m<MIN or m>MAX:
print m

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. ;-)


Yes. ;-)

Is there a way to conditionally decorate? For example if __debug__ is
True, but not if it's False? I think I've asked this question before. (?)

Cheers,
Ron
Oct 6 '05 #90
Ron Adam wrote:
Is there a way to conditionally decorate? For example if __debug__ is
True, but not if it's False? I think I've asked this question before. (?)


the decorator is a callable, so you can simply do, say

from somewhere import debugdecorator

if not __debug__:
debugdecorator = lambda x: x

or

def debugdecorator(func):
if __debug__:
...
else:
return func

etc.

</F>

Oct 6 '05 #91
Mike Meyer <mw*@mired.org> writes:
I think we're using different definitions of statically typed
here. A language that is statically typed doesn't *need* type
inferencing - the types are all declared! Type determines the thypes
by inferenceing them from an examination of the program.
I thought static typing simply means the compiler knows the types of
all the expressions (whether through declarations or inference) so it
can do type checking at compile time:
So, for instance, it can determine that this function:

def foo():
return 1

Won't ever return anything but an integer.
Static typing in this case would mean that re.match('a.*b$', foo())
would get a compile time error, not a runtime error, since re.match
expects two string arguments. This can happen through type inference
w/o declarations.

Note apropos the private variable discussion that CPython can't
guarantee that foo() always returns an integer. Something might
change foo.func_code.co_code or something like that.
Maybe you're still writing code for a language with declerations? I
never felt that need. Then again, I came to Python from a language
that didn't require declerations: Scheme.


I've done a fair amount of Lisp programming and have found the lack of
compile-time type checking to cause about the same nuisance as in
Python. I also notice that the successors to the old-time Lisp/Scheme
communities seem to now be using languages like Haskell.
Well, in the end, I would really like an *option* at the beginning of a
module file requiring variable declaration for the module. It would
satisfy both the ones who want and the ones who don't want that ...


Nope. It would just change the argument from "Python should have ..."
to "You should always use ..." or "Module foo should use ...".


Perl has a feature like that right now, and it doesn't lead to many such
arguments.
Oct 6 '05 #92
Paul Rubin <http://ph****@NOSPAM.invalid> writes:
Mike Meyer <mw*@mired.org> writes:
I think we're using different definitions of statically typed
here. A language that is statically typed doesn't *need* type
inferencing - the types are all declared! Type determines the thypes
by inferenceing them from an examination of the program.
I thought static typing simply means the compiler knows the types of
all the expressions (whether through declarations or inference) so it
can do type checking at compile time:
So, for instance, it can determine that this function:

def foo():
return 1

Won't ever return anything but an integer.


Static typing in this case would mean that re.match('a.*b$', foo())
would get a compile time error, not a runtime error, since re.match
expects two string arguments. This can happen through type inference
w/o declarations.


Except for two problems:

One you noted:
Note apropos the private variable discussion that CPython can't
guarantee that foo() always returns an integer. Something might
change foo.func_code.co_code or something like that.


Two is that dynamic binding means that foo may not refer to the above
function when you get there at run time.
Maybe you're still writing code for a language with declerations? I
never felt that need. Then again, I came to Python from a language
that didn't require declerations: Scheme.

I've done a fair amount of Lisp programming and have found the lack of
compile-time type checking to cause about the same nuisance as in
Python.


So have I - basically none at all.
> Well, in the end, I would really like an *option* at the beginning of a
> module file requiring variable declaration for the module. It would
> satisfy both the ones who want and the ones who don't want that ...

Nope. It would just change the argument from "Python should have ..."
to "You should always use ..." or "Module foo should use ...".

Perl has a feature like that right now, and it doesn't lead to many such
arguments.


As noted elsewhere, Perl isn't a good comparison. You don't simply say
"This variable exists", you say "this variable is local to this
function". Undeclared variables are dynamically bound, which means you
can get lots of non-obvious, nasty bugs that won't be caught by unit
testing. Making all your variables lexically bound (unless you really
need a dynamically bound variable) is a good idea. But that's already
true in Python.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 6 '05 #93
Fredrik Lundh wrote:
Ron Adam wrote:

Is there a way to conditionally decorate? For example if __debug__ is
True, but not if it's False? I think I've asked this question before. (?)

the decorator is a callable, so you can simply do, say

from somewhere import debugdecorator

if not __debug__:
debugdecorator = lambda x: x


Ah... thanks.

I suppose after(if) lambda is removed it would need to be.

def nulldecorator(f):
return f

if not __debug__:
debugdecorator = nulldecorator

or

def debugdecorator(func):
if __debug__:
...
else:
return func

etc.
This one came to mind right after I posted. :-)

</F>



Oct 6 '05 #94
Dans l'article <86************@bhuda.mired.org>, Mike Meyer a écrit :
Pierre Barbier de Reuille <pi************@cirad.fr> writes:
Mike Meyer a écrit :
Antoon Pardon <ap*****@forel.vub.ac.be> writes:

Op 2005-10-03, Steven D'Aprano schreef <st***@REMOVETHIScyber.com.au>:

>On Mon, 03 Oct 2005 13:58:33 +0000, Antoon Pardon wrote:

Declarations also allow easier writable closures. Since the declaration
happens at a certain scope, the run time can easily find the correct
scope when a variable is rebound.
If it happens at runtime, then you can do it without declarations:
they're gone by then. Come to think of it, most functional languages -
which are the languages that make the heaviest use of closures - don't
require variable declarations. Well, can you give a single example of such language ? Because all the
functionnal language I know but one do need variable declaration : lisp,
scheme, ocaml, haskell do need variable declaration ! Erlang do not ...


Scheme and lisp don't need variable declerations. Last time I looked,
Schemd didn't even *allow* variable declerations.


When you want local variable in lisp you do :

(let ((a 3)) (+ a 1))

For global variable you may do:

(defparameter *a* 4)

or:

(defvar *a* 4)

However, either way, variable assignment is done via :

(setf *a* 5)
(setf a 10)

This is what I call variable declaration as you have different way
to declare global variables and to assign them ... So the
two operations are well defined and different. And here there is a
difference between static language and declarative ones ... Lisp is a
dynamic language that needs variable declarations.
Only in a few cases. Type inferencing is a well-understood
technology, and will produce code as efficient as a statically type
language in most cases. Type inferencing only works for statically typed languages AFAIK ! In a
dynamically typed languages, typing a variable is simply impossible as
any function may return a value of any type !


I think we're using different definitions of statically typed
here. A language that is statically typed doesn't *need* type
inferencing - the types are all declared! Type determines the thypes
by inferenceing them from an examination of the program. So, for
instance, it can determine that this function:


Well, indeed ... statically typed means only one thing : each *variable*
has a *static* type, i.e. a type determined at compile time. Once again,
OCaml and Haskell *are* statically typed but as they have type inference
you don't *need* to explicitely type your functions / variables. However
you *may* if you want ...

def foo():
return 1

Won't ever return anything but an integer.
I think language matters shouldn't be setlled by personal preferences.
I have to agree with that. For whether or not a feature should be
included, there should either be a solid reason dealing with the
functionality of the language - meaning you should have a set of use
cases showing what a feature enables in the language that couldn't be
done at all, or could only be done clumsily, without the feature. Wrong argument ... with that kind of things, you would just stick with
plain Turing machine ... every single computation can be done with it !


"Computation" is is not the same thing as "Functionality". If you
think otherwise, show me how to declare an object with a Turing
machine.


Well, that was "bad spirit" from me ;) My argument here wasn't serious
in any mean ...

And there's also the issue of "clumsily". Turing machines are clumsy
to program in.

Except declarations don't add functionality to the language. They
effect the programing process. And we have conflicting claims about
whether that's a good effect or not, all apparently based on nothing
solider than personal experience. Which means the arguments are just
personal preferences. Well, so why not *allow* for variable declaration ? Languages like Perl
does that successfully ... you don't like : you don't do ! you like :
you do ! A simple option at the beginning of the file tell the compilor
if variable declaration is mandatory or not !


Perl is a red herring. Unless it's changed radically since I last
looked, undeclared variables in Perl have dynamic scope, not lexical
scope. While dynamically scoped variables are a powerful feature, and
there have been proposals to add them to Python, having them be the
default is just *wrong*. If I were writing in Perl, I'd want
everything declared just to avoid that. Of course, if Python behaved
that way, I'd do what I did with Perl, and change languages.


I never said to adopt the whole Perl variable semantic. I just pointed
what I think is a good idea in Perl and that help (IMHO) precising what
I intended ...
Antoon, at a guess I'd say that Python is the first time you've
encountered a dynamnic language. Being "horrified" at not having
variable declarations, which is a standard feature of such languages
dating back to the 1950s, is one such indication. Dynamic language and variable declaration are non-related issues ! You
can have statically-typed language without variable declaration (i.e.
BASIC) and dynamically-typed language with (i.e. Lisp) ! Please, when
you says something about languages, at least give 1 name of language
asserting what you're saying !


Declerations and typing are *also* non-related issues. See Perl. Also
see the subject line.


That was just my point ...
Dynamic languages tend to express a much wider range of programming
paradigms than languages that are designed to be statically
compiled. Some of these paradigms do away with - or relegate to the
level of "ugly performance hack" - features that someone only
experienced with something like Pascal would consider
essential. Assignment statements are a good example of that. Well, could you be more specific once more ? I can't that many paradigm
only available on dynamically typed languages ... beside duck-typing
(which is basically a synonym for dynamically-typed)


I said "dynamic languages", *not* "dynamically typed languages". They
aren't the same thing. Dynamic languages let you create new functions,
variables and attributes at run time. Python lets you delete them as
well. This means that simle declarations can't tell you whether or
not a variable will exist at runtime, because it may have been added
at run time.


Ok, I misunderstood ... however, can you still point some *usefull*
paradigm available to dynamic languages that you cannot use with static
ones ? As there are so many, it shouldn't be hard for you to show us
some !
Given these kinds of differences, prior experience is *not* a valid
reason for thinking that some difference must be wrong. Until you have
experience with the language in question, you can't really decide that
some feature being missing is intolerable. You're in the same position
as the guy who told me that a language without a goto would be
unusable based on his experience with old BASIC, FORTRAN IV and
assembler.

After more than two years of Python programming, I still fill the need
for variable declarations. It would remove tons of bugs for little works
and would also clarify the scope of any single variable.


Maybe you're still writing code for a language with declerations? I
never felt that need. Then again, I came to Python from a language
that didn't require declerations: Scheme.
Pick one of the many languages that don't require declarations. Try
writing a code in them, and see how much of a problem it really is in
practice, rather than trying to predict that without any
information. Be warned that there are *lots* of variations on how
undeclared variables are treated when referenced. Python raises
exceptions. Rexx gives them their print name as a value. Other
languages do other things.

Well, IMO, worst case is silently give a default value, like PHP (or
apparently Rexx) does ... this can hide bugs for month if a single
test-case is missing !

Well, in the end, I would really like an *option* at the beginning of a
module file requiring variable declaration for the module. It would
satisfy both the ones who want and the ones who don't want that ...


Nope. It would just change the argument from "Python should have ..."
to "You should always use ..." or "Module foo should use ...".

<mike

--
BOFH excuse #413:

Cow-tippers tipped a cow onto the server.
Oct 6 '05 #95
Ron Adam wrote:
Fredrik Lundh wrote:

Ron Adam wrote:
Is there a way to conditionally decorate? For example if __debug__ is
True, but not if it's False? I think I've asked this question before. (?)

the decorator is a callable, so you can simply do, say

from somewhere import debugdecorator

if not __debug__:
debugdecorator = lambda x: x

Ah... thanks.

I suppose after(if) lambda is removed it would need to be.

def nulldecorator(f):
return f

if not __debug__:
debugdecorator = nulldecorator

It would be easier to write

if not __debug__:
def debugdecorator(f):
return f

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 6 '05 #96
Barbier de Reuille <pi************@cirad.fr> writes:
Dans l'article <86************@bhuda.mired.org>, Mike Meyer a écrit :
Pierre Barbier de Reuille <pi************@cirad.fr> writes:
Mike Meyer a écrit :
Antoon Pardon <ap*****@forel.vub.ac.be> writes:

>Op 2005-10-03, Steven D'Aprano schreef <st***@REMOVETHIScyber.com.au>:
>
>>On Mon, 03 Oct 2005 13:58:33 +0000, Antoon Pardon wrote:
>
>Declarations also allow easier writable closures. Since the declaration
>happens at a certain scope, the run time can easily find the correct
>scope when a variable is rebound.
If it happens at runtime, then you can do it without declarations:
they're gone by then. Come to think of it, most functional languages -
which are the languages that make the heaviest use of closures - don't
require variable declarations.
Well, can you give a single example of such language ? Because all the
functionnal language I know but one do need variable declaration : lisp,
scheme, ocaml, haskell do need variable declaration ! Erlang do not ...
Scheme and lisp don't need variable declerations. Last time I looked,
Schemd didn't even *allow* variable declerations.


When you want local variable in lisp you do :

(let ((a 3)) (+ a 1))


Excep that's not a decleration, that's a binding. That's identical to
the Python fragment:

a = 3
return a + 1

except for the creation of the new scope. Not a variable decleration
in site.
For global variable you may do:

(defparameter *a* 4)

or:

(defvar *a* 4)
That's not Scheme. When I was writing LISP, those weren't
required. Which is what I said: variable declarations aren't required,
and aren't allowedd in Scheme.
However, either way, variable assignment is done via :

(setf *a* 5)
(setf a 10)

This is what I call variable declaration as you have different way
to declare global variables and to assign them ... So the
two operations are well defined and different.
Python uses "global foo" to declare global variables.
And here there is a difference between static language and
declarative ones ... Lisp is a dynamic language that needs variable
declarations.


LISP doesn't need variable declarations. I certainly never wrote any
when I was writing it.
Except declarations don't add functionality to the language. They
effect the programing process. And we have conflicting claims about
whether that's a good effect or not, all apparently based on nothing
solider than personal experience. Which means the arguments are just
personal preferences.
Well, so why not *allow* for variable declaration ? Languages like Perl
does that successfully ... you don't like : you don't do ! you like :
you do ! A simple option at the beginning of the file tell the compilor
if variable declaration is mandatory or not !


Perl is a red herring. Unless it's changed radically since I last
looked, undeclared variables in Perl have dynamic scope, not lexical
scope. While dynamically scoped variables are a powerful feature, and
there have been proposals to add them to Python, having them be the
default is just *wrong*. If I were writing in Perl, I'd want
everything declared just to avoid that. Of course, if Python behaved
that way, I'd do what I did with Perl, and change languages.


I never said to adopt the whole Perl variable semantic. I just pointed
what I think is a good idea in Perl and that help (IMHO) precising what
I intended ...


And I pointed out that it's a good idea in Perl because it does
something that it doesn't need doing in Python.
Dynamic languages tend to express a much wider range of programming
paradigms than languages that are designed to be statically
compiled. Some of these paradigms do away with - or relegate to the
level of "ugly performance hack" - features that someone only
experienced with something like Pascal would consider
essential. Assignment statements are a good example of that.
Well, could you be more specific once more ? I can't that many paradigm
only available on dynamically typed languages ... beside duck-typing
(which is basically a synonym for dynamically-typed)

I said "dynamic languages", *not* "dynamically typed languages". They
aren't the same thing. Dynamic languages let you create new functions,
variables and attributes at run time. Python lets you delete them as
well. This means that simle declarations can't tell you whether or
not a variable will exist at runtime, because it may have been added
at run time.

Ok, I misunderstood ... however, can you still point some *usefull*
paradigm available to dynamic languages that you cannot use with static
ones ? As there are so many, it shouldn't be hard for you to show us
some !


I find the ability to add attributes to an object or class at run time
useful.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Oct 6 '05 #97
On 6 Oct 2005 06:44:41 GMT, Antoon Pardon <ap*****@forel.vub.ac.be> wrote:
Op 2005-10-06, Bengt Richter schreef <bo**@oz.net>:
On 5 Oct 2005 09:27:04 GMT, Duncan Booth <du**********@invalid.invalid> wrote:
Antoon Pardon wrote:

It also is one possibility to implement writable closures.

One could for instace have a 'declare' have the effect that
if on a more inner scope such a declared variable is (re)bound it
will rebind the declared variable instead of binding a local name.

That is one possibility, but I think that it would be better to use a
keyword at the point of the assigment to indicate assignment to an outer
scope. This fits with the way 'global' works: you declare at (or near) the
assignment that it is going to a global variable, not in some far away part
of the code, so the global nature of the assignment is clearly visible. The
'global' keyword itself would be much improved if it appeared on the same
line as the assignment rather than as a separate declaration.

e.g. something like:

var1 = 0

def f():
var2 = 0

def g():
outer var2 = 1 # Assign to outer variable
global var1 = 1 # Assign to global
IMO you don't really need all that cruft most of the time. E.g., what if ':='
meant 'assign to variable wherever it is (and it must exist), searching according
to normal variable resolution order (fresh coinage, vro for short ;-), starting with
local, then lexically enclosing and so forth out to module global (but not to builtins).'


Just some ideas about this

1) Would it be usefull to make ':=' an expression instead if a
statement?

Some people would think so, but some would think that would be tempting the weak ;-)

I think the most important reason that the assignment is a statement
and not an expression would apply less here because '==' is less easy
to turn into ':=' by mistake than into =

Even if people though that kind of bug was still too easy

2) What if we reversed the operation. Instead of var := expression,
we write expression =: var.

IMO this would make it almost impossible to write an assignment
by mistake in a conditional when you meant to test for equality.

It's an idea. You could also have both, and use it to differentiate
pre- and post-operation augassign variants. E.g.,

alist[i+:=2] # add and assign first, index value is value after adding

alist[i=:+2] # index value is value before adding and assigning

Some people might think that useful too ;-)

Hm, I wonder if any of these variations would combine usefully with the new
short-circuiting expr_true if cond_expr else expr_false ...

Sorry I'll miss the flames, I'll be off line a while ;-)

Regards,
Bengt Richter
Oct 6 '05 #98
Op 2005-10-06, Diez B. Roggisch schreef <de***@nospam.web.de>:
Suppose we have a typesystem which has the type ANY, which would mean
such an object could be any type. You could then have homogenous lists
in the sense that all elements should be of the same declared type and
at the same time mix all kind of type in a particular list, just
as python does.


The you have JAVA Object or C void*. Which cause all kinds of runtime
troubles.... because they essentially circumvene the typechecking!


Why do you call this a JAVA Object or C void*? Why don't you call
it a PYTHON object. It is this kind of reaction that IMO tells most
opponents can't think outside the typesystems they have already
seen and project the problems with those type systems on what
would happen with python should it acquire a type system.
So how would this limit python.


The limitation is that in static languages I must _know_ what type to
cast such an ANY, before calling anything on it. Otherwise its useless.
even though ususally the contents of a list
share some common behaviour. And that exactly is the key point here: in
a statically typed world, that common behaviour must have been extracted
and made explicit.

Would my suggestion be classified as a statically typed world?


See above.


Your answer tells more about you then about my suggestion.

--
Antoon Pardon
Oct 7 '05 #99
Antoon Pardon wrote:
Op 2005-10-06, Diez B. Roggisch schreef <de***@nospam.web.de>:
Suppose we have a typesystem which has the type ANY, which would mean
such an object could be any type. You could then have homogenous lists
in the sense that all elements should be of the same declared type and
at the same time mix all kind of type in a particular list, just
as python does.
The you have JAVA Object or C void*. Which cause all kinds of runtime
troubles.... because they essentially circumvene the typechecking!

Why do you call this a JAVA Object or C void*? Why don't you call
it a PYTHON object. It is this kind of reaction that IMO tells most
opponents can't think outside the typesystems they have already
seen and project the problems with those type systems on what
would happen with python should it acquire a type system.

[sigh]. No, it's just you being you. Diez' intention seemed fairly clear
to me: he is pointing out that strongly-typed systems invariably fall
back on generic declarations when they want to allow objects of any type
(which, it seems to me, is what you were proposing as well).

In other words, you want Python to be strongly-typed, but sometimes you
want to allow a reference to be to any object whatsoever. In which case
you can't possibly do any sensible type-checking on it, so this new
Python+ or whatever you want to call it will suffer from the same
shortcomings that C++ and java do, which is to say type checking can't
possibly do anything useful when the acceptable type of a reference is
specified as ANY.
So how would this limit python.


The limitation is that in static languages I must _know_ what type to
cast such an ANY, before calling anything on it. Otherwise its useless.

even though ususally the contents of a list
share some common behaviour. And that exactly is the key point here: in
a statically typed world, that common behaviour must have been extracted
and made explicit.
Would my suggestion be classified as a statically typed world?


See above.

Your answer tells more about you then about my suggestion.

Damn, I've been keeping away from this thread lest my exasperation lead
me to inappropriate behaviour.

Is there any statement that you *won't* argue about?

leaving-the-(hopefully)-last-word-to-you-ly y'rs - steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC www.holdenweb.com
PyCon TX 2006 www.python.org/pycon/

Oct 7 '05 #100

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by zoe | last post: by
5 posts views Thread by Andrej Prsa | last post: by
2 posts views Thread by William Ahern | last post: by
5 posts views Thread by shaanxxx | last post: by
19 posts views Thread by Spiros Bousbouras | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.