Closures in leu of pointers?

S

Steven D'Aprano

Python require declarations for local names, but if it did it would
probably use "local".

Oops, I meant *doesn't* require declarations. Sorry for the error.
 
M

Michael Torrie

You are absolutely correct in principle. But in practice, there are ten
bazillion C, Pascal, COBOL, and BASIC programmers who understand the word
"variable" to mean a named memory location, for every Smalltalk or Lisp
programmer who understands a "variable" as a name binding. So it's pure
weight of numbers thing.

The average Lisp programmer will be completely aware that "variable" can
mean various things, and take care to determine what the word means in
Python. She will immediately grok what we mean, even if she thinks that
the "no variables" part is just an affectation ("Heh, those wacky Python
dudes think they don't have variables!") but at least she'll understand
the name binding part.

On the other hand, the average C programmer is barely aware that there
are other languages at all, let alone that some of them differ from C in
semantics as well as syntax. So by emphasising the differences ("Python
has no variables? It has name bindings?") we increase the likelihood that
he'll learn the differences in semantics as well as syntax.

So, in a very practical sense, "Python has no variables, it has name
bindings" is completely wrong except in the sense that really matters:
Python's variables don't behave identically to C variables.

Very good points. Thank you. Good tips for how to better explain
things next time it comes up. I'll avoid simply saying "Python has no
variables."
 
R

rusi

You are absolutely correct in principle. But in practice, there are ten
bazillion C, Pascal, COBOL, and BASIC programmers who understand the word
"variable" to mean a named memory location, for every Smalltalk or Lisp
programmer who understands a "variable" as a name binding. So it's pure
weight of numbers thing.

I note that the 10 bazillion C… programmers take precedence over 10 centuries of mathematics. I wonder if you are familiar with Weizenbaum -- early doyen of AI. Here is a conversation whose first few paras are relevant
http://tech.mit.edu/V105/N16/weisen.16n.html

On a more technical note... that imperative programming is a bad idea is one of the harder-to-learn lessons for computer scientists
http://blog.languager.org/2012/11/imperative-programming-lessons-not.html
 
S

Steven D'Aprano

Python's
basic data types are immutable. At best we could say they are read-only
variables.

Python's basic data types are not necessarily immutable. Lists and dicts
are not immutable. Being a high-level language, the idea of "primitives"
like int, double, float, etc from C doesn't really apply. A Python dict
is not made up from Python ints. Both int and dict are equally "basic".

More importantly, you are conflating the idea of a variable (a name) and
the value of that variable (a value). Whether a variable is a named
memory location or a name binding in a namespace, it's still a name. Ints
are not names, whether they are low-level C ints or Python int objects.
Comparing the immutability of an int object (value) with the ability to
write to a name ("read-only variable" == constant) confuses the value and
the name, which is exactly what we're trying to get away from.

So no, saying Python doesn't have variables is not the same as saying C
doesn't have variables but only memory locations. They are different
concepts entirely, though on the surface they look similar.

Antoon is suggesting that instead of defining:

"A variable is a named memory location, like in C"

and therefore concluding that Python doesn't have variables, we could
define:

"A variable is a name in a namespace bound to a value, like in Lisp"

and therefore conclude that Python does have variables, but C doesn't.

It's not that the two definitions are "different concepts entirely", but
that they are two subtly different forms of the same concept, a mapping
between names and values.

If they were entirely different concepts, like a list and an int, you
wouldn't have people confusing them. Nobody ever asks why Python doesn't
let you sort an int, or take the square of a list...
 
C

cts.private.yahoo

exactly that. Without wanting to analyze it in too much depth now, I would want a local keyword to allow me to know I was protecting my variables, and a way to specify other scopes, without so much implied scoping in non-intuitive ways...

Now everybody is gonna tell me how wrong I am, but you asked what I want, and that's what keeps aggrevating me with python.
 
I

Ian Kelly

Op 29-06-13 16:02, Michael Torrie schreef:



I don't understand why members of this list keep saying this. Sure the
variables in python behave differently than those in C and algol But they
behave similarly as those in smalltalk and lisp and I haven't seen
anyone claim that smalltalk and lisp don't have variables.

Perhaps because that is the terminology used by the language documentation:

http://docs.python.org/3/reference/executionmodel.html#naming-and-binding
 
S

Steven D'Aprano

exactly that.

Exactly what? Who are you replying to? Your post has no context.

Without wanting to analyze it in too much depth now, I
would want a local keyword to allow me to know I was protecting my
variables, and a way to specify other scopes, without so much implied
scoping in non-intuitive ways...

Huh? What language are you programming in? Python doesn't have implied
scoping in non-intuitive ways.

Python does have a way to specify other scopes: global to enable writing
to the global scope, and in Python 3, nonlocal to specify writing to a
nonlocal scope.

And what on earth does "protecting my variables" mean? If it means what I
think it means, Python gives it to you for free: you cannot overwrite a
variable outside of the local scope without declaring it first. What more
"protection" do you want?

Now everybody is gonna tell me how wrong I am, but you asked what I
want, and that's what keeps aggrevating me with python.

If you want <language X>, you know where to find it.

Perhaps you will find it less aggravating to worry more about the
concrete problem you want to solve, than the metaproblem of how to
program Perl using Python syntax.
 
T

Tim Chase

Nobody ever asks why Python doesn't let you sort an int, or take
the square of a list...

just to be ornery, you can sort an int:
'112345569'

And I suppose, depending on how you define it, you can square a list:
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'a'), ('b',
'b'), ('b', 'c'), ('b', 'd'), ('c', 'a'), ('c', 'b'), ('c', 'c'),
('c', 'd'), ('d', 'a'), ('d', 'b'), ('d', 'c'), ('d', 'd')]

Or, if you want to do it frequently, Python graciously even allows
you to do things like
.... def __pow__(self, power):
.... return list(itertools.product(*([self] * power)))
....[('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'a'), ('b',
'b'), ('b', 'c'), ('b', 'd'), ('c', 'a'), ('c', 'b'), ('c', 'c'),
('c', 'd'), ('d', 'a'), ('d', 'b'), ('d', 'c'), ('d', 'd')]


:)

-tkc
 
I

Ian Kelly

Huh? What language are you programming in? Python doesn't have implied
scoping in non-intuitive ways.

def f(x):
def g(y):
print(x)
x = y

Within g, the variable x is implicitly local, which is non-intuitive
since without the assignment it would not be.

That said, while I think a local keyword would not be unwelcome, I
would not want it to be required. Otherwise we end up with the
scoping rules of Lua, where everything is global unless explicitly
marked as local.
 
J

Joshua Landau

just to be ornery, you can sort an int:

'112345569'

To be yet more ornery, you are merely sorting the string
representation of an int.

You can sort an int, though:

[1].sort()

You may say "No! You are sorting a *list*!" However, is it not fair to
say that with:

[1, 2, 3, 4, 5].sort()

you are sorting integers? That is just a common english idiom. Hence,
"[1].sort()" sorts an int.
And I suppose, depending on how you define it, you can square a list:
From Wikipedia, "a square is the result of multiplying a number, or
other expression, by itself. In other words, squaring is
exponentiation to the power 2."

This means that the only logical definitions would be "list*list" and "list**2".

However, it can be done!

class PowList(list):
def __pow__(self, other): pass

PowList([1, 2, 3])**2

// Because being a pedant is more fun when you're doing it competitively //
 
T

Terry Reedy

def f(x):
def g(y):
print(x)
x = y

Within g, the variable x is implicitly local,

The assignment looks pretty explicit to me ;-|. But to each his own on
'plicitness.
which is non-intuitive
since without the assignment it would not be.

I think the problem people have is this. Python is *not* an interpreted
language in the traditional sense: read a line, interpret and execute
it. It is compiled, and the compilation of functions is a two pass
affair. The first pass classifies all names. The second pass generates
code based on the classification of the first pass. This is not part of
the grammar, but implied (required) by the semantic description.

If, in the general case, the compiler requires two passes to understand
a function body, then *so do people*#. This requirement is what trips up
people who are either not used to the idea of two-pass compilation or do
not cognize that the language requires it.

# The alternative for either program or people is a 1-pass +
backtracking process where all understandings are kept provisional until
the end of the body and revised as required. 2 passes are simpler.

That said, writing deceptive but functionin code is usually bad style.
Writing code that looks functional but is buggy is worse.
 
I

Ian Kelly

# The alternative for either program or people is a 1-pass + backtracking
process where all understandings are kept provisional until the end of the
body and revised as required. 2 passes are simpler.

Or simply an explicit declaration of scope at the beginning of the
function definition.
 
C

cts.private.yahoo

No, actually, it's okay that it's local by default, after all. TCL's got that capability of explicitly specifying the scope (up n or something like that?). That's okay for tcl, not sure if it would seem so elegant for python. But you can't tell me that the scenarios that I presented in the beginning of this thread are intuitive. I'm going to have a very hard time ever accepting a language that lets me read a variable but when I try to write to it, it suddenly doesn't want to have to do with it anymore ... but hey, like somebody said - everybody's got their own sense of 'plictedness.
 
M

Michael Torrie

Python's basic data types are not necessarily immutable. Lists and dicts
are not immutable. Being a high-level language, the idea of "primitives"
like int, double, float, etc from C doesn't really apply. A Python dict
is not made up from Python ints. Both int and dict are equally "basic".

Indeed. Sorry for not being more clear. I was referring primarily to
numeric objects and strings.
 
M

Michael Torrie

exactly that. Without wanting to analyze it in too much depth now, I
would want a local keyword to allow me to know I was protecting my
variables, and a way to specify other scopes, without so much implied
scoping in non-intuitive ways...

The technical thing you are trying to accomplish, is, as far as I know,
not easily doable in Python, except if you use a mutable object like a list.
Now everybody is gonna tell me how wrong I am, but you asked what I
want, and that's what keeps aggrevating me with python.

I presume you're answering the question of "what is it you're trying to
do." Can't be sure. But chances are good.

Far be it from me to tell you how wrong you are. I'm still not even
sure what you're trying to do ultimately.
 
S

Steven D'Aprano

just to be ornery, you can sort an int:

'112345569'

And I suppose, depending on how you define it, you can square a list:


Yeah, but my point is that nobody ever *asks* how to do it, because they
don't confuse the two concepts. Those who have some need for sorting the
digits of an int-as-string work out how to solve the problem without
asking.

And you'll note I didn't say that nobody confuses an int and a string.
That was no accident :)
 
T

Terry Reedy

Or simply an explicit declaration of scope at the beginning of the
function definition.

One of the reasons I switched to Python was to not have to do that, or
hardly ever. For valid code, an new declaration is hardly needed.
Parameters are locals. If the first use of another name binds it (and
that includes import, class, and def), it is local. If the first use of
does not bind it, it had better not be local (because if it is, there
well be an exception). If there are branches, each should be consistent
with the others. One should only need two readings to understand and fix
unbound local errors.
 
C

Chris Angelico

One of the reasons I switched to Python was to not have to do that, or
hardly ever. For valid code, an new declaration is hardly needed. Parameters
are locals. If the first use of another name binds it (and that includes
import, class, and def), it is local. If the first use of does not bind it,
it had better not be local (because if it is, there well be an exception).
If there are branches, each should be consistent with the others. One should
only need two readings to understand and fix unbound local errors.

This is strictly a matter of opinion, and one on which mine differs
from yours. I think explicit declarations are better than implicit
"you've assigned to this name" local creations; the declarations help
to catch typos. Also, I like the consistency of C-style declarations -
where-ever you declare something, it's valid from there "in", and not
"out". Without declarations, there's a magical scope boundary at a
function definition that's different from the non-boundary at a loop,
for instance.

But that's just my opinion. and as Teresa says, I'm only one, and
possibly I'm wrong.

ChrisA
 
I

Ian Kelly

One of the reasons I switched to Python was to not have to do that, or
hardly ever. For valid code, an new declaration is hardly needed. Parameters
are locals. If the first use of another name binds it (and that includes
import, class, and def), it is local. If the first use of does not bind it,
it had better not be local (because if it is, there well be an exception).
If there are branches, each should be consistent with the others. One should
only need two readings to understand and fix unbound local errors.

In general I agree, although when reading code I would definitely
prefer if the locals were declared.

On a related note, I think that generator functions should in some way
be explicitly marked as such in the declaration, rather than needing
to scan the entire function body for a yield statement to determine
whether it's a generator or not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,087
Messages
2,570,600
Members
47,222
Latest member
jspanther

Latest Threads

Top