binding vs rebinding

Hello, I wonder why there is no difference in syntax between binding and rebinding. Obviously, the semantics is not at all the same, for humans as well as for the interpreter: * Binding: create a name, bind a value to it. * Rebinding: change the value bound to the name. I see several advantages for this distinction and no drawback. The first advantage, which imo is worthful enough, is to let syntax match semantics; as the distinction *makes sense*. A nice side-effect would be to allow detection of typographic or (human ;-) memory errors: * When an error wrongly and silently creates a new name instead of launching a NameError exception. A distinct syntax for rebinding would prevent that. * When an error wrongly and silently rebinds an existing name instead of launching a NameError exception. A distinct syntax for (first) binding would prevent that. No need, I guess, to insist on the fact that such errors sometimes lead to long and difficult debugging precisely for they are silent. This, because in all cases "a=1" is a valid instruction, as there is no distinction between binding and rebinding. I suspect a further advantage may be to get rid of "global" and "nonlocal" declarations -- which, as I see it, do not at all fit the python way. I may be wrong on that, still it seems such declarations are necessary only because of the above distinction lacking. My rational on this is: * It is very common and helpful to allow a local variable beeing named identically as another one in an external scope. * There is no binding/redinding distinction in python syntax. * So that whenever a name appears on the left side of an assignment, inside a non-global scope, there is no way to know whether the programmer intends to create a local name or to access a possibly existing external name. * To resolve this ambiguity, python adopts the rule of creating a local name. * Thus, it becomes impossible to rebind an external name from a local scope. Which is still useful in rather rare, but relevant, use cases. * So that 'global', and later 'nonlocal', declarations had to be introduced in python. (I tried to be as clear and step-by-step as I can so that this reasoning can easily be refuted if ever it holds errors I cannot see.) It seems that if ever the second step would not hold, then there would be no reason for such declarations. Imagine that rebinbing is spellt using ':='. Then, from a non-glocal scope: * a=1 causes creation of a local name * a:=1 rebinds a local name if exists, or rebinds an external name if exists (step-by-step up to module level scope), or else launches NameError. There may be reasons why such a behaviour is not the best a programmer would expect: I wait for your comments. Obviously, for the sake of compatibility, this is more a base for discussion, if you find the topic interesting, than for a proposal for python 9000... Denis PS: As a reference to the thread on the sign ':' at the end of block headlines, the syntactic format I would actually enjoy is: * binding name : value * rebinding name :: value ------ la vida e estranya

spir wrote:
I like the idea. On the global/nonlocal thing, it would be possible that a nested function does a:=l and there is both a nonlocal "a" and a global "a". The current global/nonlocal mechanism allows the programmer to disambiguate this case. But it is hard to imagine use cases where this couldn't be resolved by renaming one of the "a" variables. And the same problem occurs in the current mechanism where a function nested 2 levels down has two nonlocal "a" variables: in its direct parent, and in its grandparent. -bruce

On Thu, Feb 5, 2009 at 1:22 PM, spir <denis.spir@free.fr> wrote:
How would you write code like: my_result = [] for item in items: a = <some intermediate result computed from item> ... my_result.append(<something computed from a>) where a is bound for the first time on the first iteration of the loop, and rebound on all subsequent iterations? Mark

On Thu, Feb 5, 2009 at 17:12, Mark Dickinson <dickinsm@gmail.com> wrote:
It would be bound locally to the body of the loop. -- Marcin Kowalczyk qrczak@knm.org.pl http://qrnik.knm.org.pl/~qrczak/

On Thu, Feb 5, 2009 at 5:22 AM, spir <denis.spir@free.fr> wrote:
It was proposed and rejected for Python 3000, so it's unlikely (though not impossible) to be changed. See PEP 3099 (http://www.python.org/dev/peps/pep-3099/ : "There will be no alternative binding operators such as :=") and http://mail.python.org/pipermail/python-dev/2006-July/066995.html I haven't read the thread to see what the reasoning was, but I trust Guido's judgement, Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com

spir <denis.spir@free.fr> writes:
* Binding: create a name, bind a value to it. * Rebinding: change the value bound to the name.
That's not obvious. The semantics could just as well be described as: * Binding: bind this name to that value. * Rebinding: bind this name to that value. If I claimed this semantic description as “obvious”, I'd be just as wrong to do so. But this description functions very well to explain the semantics of these operations for me and others.
Since I see no sense in the distinction, I see the drawback of unnecessarily complicating the syntax. -- \ “I went to a garage sale. ‘How much for the garage?’ ‘It's not | `\ for sale.’” —Steven Wright | _o__) | Ben Finney

Le Fri, 06 Feb 2009 08:31:58 +1100, Ben Finney <ben+python@benfinney.id.au> a écrit :
You are right do describe it like that. I agree that the point of view is not wrong. However, * At the interpreter level, as far as I know, rebinding does not create the name like if it was unknown. (Note that a similar issue happens with dicts.) * At the programmer level, changing the value associated to a name is really a different action than introducing and giving an initial value to a new symbol. For me, *this* is the relevant point: even if the language would behave "behind the scene" the same way in both cases. This is implantation concern. A pertinent objection has been raised already in the case of loops: for item in container: # temp symbol foo = func(item) # process do_stuff Conceptually, there is a foo for each item. Obviously, we cannot express that properly, because the loop's body is the same for each iteration. The issue here lies in the fact that a loop does not introduce a local namespace, while this is precisely what we *mean* when defining such as utility variable as foo. In other words: there is a distortion between language semantics and modelizing semantics. Denis ------ la vida e estranya

spir wrote:
Both binding and rebinding actions are identical.
Whatever implementation difference there may be is transparent at the interpreter level.
* At the programmer level, changing the value associated to a name is really a different action than introducing and giving an initial value to a new symbol. For me, *this* is the relevant point: even if the language would behave "behind the scene" the same way in both cases. This is implantation concern.
I disagree. At the programmer level, x=5 is the same thing whether x already exists or not.
Speak for yourself. When I use a for loop, I do not expect or want it to create a new namespace.
In other words: there is a distortion between language semantics and modelizing semantics.
I disagree. I think the language semantics match precisely the semantics of name binding as I expect it. -- Steven

spir wrote:
Hello,
I wonder why there is no difference in syntax between binding and rebinding. Obviously, the semantics is not at all the same, for humans as well as for the interpreter:
Denis, as you can see from the above line, your email breaks the Internet standard of using hard-line breaks within paragraphs. This causes problems for other people. Please set your mail client to wrap text at 68, 70 or 72 characters.
In Python, names are stored in namespaces, which are implemented as dictionaries. There is a nice correspondence between the syntax of namespaces and of dicts: x = 1 # create a new name and bind it to 1 x = 2 # rebind name to 2 del x # delete name mydict['x'] = 1 # create new key and bind it to 1 mydict['x'] = 2 # rebind key to 2 del mydict['x'] # delete key Also, your suggestion is conceptually the same as requiring declarations: x = 1 # declare x with value 1 x := 2 # assign to x Finally, what should we do here? if flag: x = 2 print foo(x) x = 3 # is this a rebinding or a new binding? print bar(x) -- Steven

Le Fri, 06 Feb 2009 08:51:14 +1100, Steven D'Aprano <steve@pearwood.info> a écrit :
Good point, yes, this holds for dicts, too! mydict['x'] := bar # ==> KeyError: mydict['x'] does not exist. mydict['x'] = 1 # create new key and bind it to 1 mydict['x'] := 2 # (syntax suggestion) rebind key to 2 mydict['x'] = foo # ==> KeyError: mydict['x'] already exists.
Hem... well, you can actually see it like that. The main difference is that, unlike in "declarative" languages, there is no declaration without binding. var foo; int i # not in python So that I would rather call that 'initialization' (== declaration + first binding) as opposed to 'rebinding'.
Interesting, thank you. Now comes on stage the naming problem. What is here expressed is an optional additional step, right? This is written as a special case where whatever is symbolized with 'x' will take a specific value. Later the program enters back the main flow and this thing will have a standard value. I assert that the same name should not be used for both special and standard cases. This imo shows a lack of distinction. Using a different name will make things clearer: if flag: # 'flag' expresses a special case flag_x = 2 # possibly reuse the case name as prefix print foo(flag_x) x = 3 # is this a rebinding or a new binding? print bar(x) I am rather sure that in any concrete model, once the distinction is made clear, then obvious naming can be found. if ambiguity: ambiguity_message = 'ambiguity warning: "%s"\n' % ambiguous_expr print warning_format(message) message = "\t%s\n" % line_body print standard_format(message) Probably most name rebindings rather express a lack of distinction that makes the code obscure. Haven't you ever read things like: config = "config.txt" # string: name config = open(config) # file object config = config.read() # string: content config = config.lines() # array of strings config = parse(config) # e.g. custom object Denis ------ la vida e estranya

spir wrote:
I assert that once you've gotten to the point of suggesting that people change the way they program, you've lost the debate. :) "Practicality beats purity." How many other languages support this split between binding and rebinding? How many of them are popular? (What's the highest rank that one of them has on, say, http://www.tiobe.com/content/paperinfo/tpci/index.html ?) (Don't take this to mean that I disagree with you. I think that if people either had to say when they were rebinding names, or couldn't rebind names (a la Erlang), programs would probably be more stable. But Python isn't the kind of language to do that sort of thing in. I feel it would fit in better with a more academic language like Haskell or Scheme.)
I don't see that code as particularly obscure. Sure you could re-write it to use a billion different temporary variables (but you'ld better make sure they didn't conflict with ones above you!), but that doesn't really help anything from my point of view, and this example (with the addition of some extra syntax) would still be legal in the rebinding-version of Python you're suggesting. Later, Blake.

On Fri, Feb 6, 2009 at 15:38, Blake Winton <bwinton@latte.ca> wrote:
1. Java - split 2. C - split 3. C++ - split 4. (Visual) Basic - split 5. PHP - not split 6. C# - split 7. Python - not split 8. Perl - split 9. JavaScript - split 10. Delphi - split 11. Ruby - not split -- Marcin Kowalczyk qrczak@knm.org.pl http://qrnik.knm.org.pl/~qrczak/

Marcin 'Qrczak' Kowalczyk wrote:
Are you counting the implicit lack of a binding as a binding? "int x;" does not bind anything to "x", technically the first time "x = ..." appears is the first binding. Maybe I am splitting hairs, but this whole topic is a hair splitter.
In addition to the debate above, the declarations are optional in these languages, and in that case, they are very much the same semantics as Python.
With regard to *all* of these languages there is *not* a separate assignment operator, only possibly a special statement (which in none of these languages *require* the initial assignment). And since the debate is about a special operator and not a special statement, all of these languages support dropping this discussion. It really is that foreign. -- Scott Dial scott@scottdial.com scodial@cs.indiana.edu

On Fri, Feb 6, 2009 at 11:43 AM, Scott Dial <scott+python-ideas@scottdial.com> wrote:
Java and C# will always bind a default value on the declaration (even without the "="); C++ sometimes does, and C never does (at least not according to whichever standard I vaguely remember). But there's not really any point in discussing this as a language feature independently of scoping, and none of these languages have scoping semantics that are a good match for Python. -- Curt Hagenlocher curt@hagenlocher.org

On Fri, Feb 6, 2009 at 20:43, Scott Dial <scott+python-ideas@scottdial.com> wrote:
I am treating as "split" languages which distinguish introducing a new variable in the current scope from assignment to an existing variable. Or, in other words, languages where assignment alone cannot be used to create a new local variable. When a variable is introduced, its value can be given explicitly, or it can be assumed to be some default (possibly depending on the type), or it can be unspecified, or it can require further rebinding. Usually there is a choice between the first and some of the others. I do not consider these differences.
"int x;" does not bind anything to "x",
It creates an object of type int and binds the name x to it. The object initially has an unspecified value, and can have its value changed. The association between usages of x in this scope and this object cannot be changed.
In Perl you can assign to an non-existing variable, which is in this case assumed to be global (and you get a warning if warnings are turned on). In non-trivial programs they are local variables which matter. For JavaScript: http://www.webdevelopersnotes.com/tutorials/javascript/global_local_variable... For Visual Basic: http://msdn.microsoft.com/en-us/library/1t0wsc67(VS.80).aspx For Delphi: http://delphi.about.com/od/beginners/l/aa060899.htm All these languages have a syntax for introducing a variable, distinct from assignment to an existing variable, and that syntax is needed for creating a local variable in a function scope. -- Marcin Kowalczyk qrczak@knm.org.pl http://qrnik.knm.org.pl/~qrczak/

Le Fri, 6 Feb 2009 21:47:26 +0100, "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl> a écrit :
You are thus enlarging the topic to languages where it is possible to introduce a name without any *explicit* binding. As the title of the thread shows, this was not my initial intention, but I must recognize this is pertinent -- see bottom of the message. This debate has proved fruitful I guess, thank you very much. Maybe it's time to close it as probably we have explored the topic enough and this aspect of python will not change in a previsible future. I will try sum up fairly the main discussion points -- feel free to criticize ;-). My startup assertion was that (first) binding and rebinding are conceptually different actions, worth beeing distinguished in syntax (I wrote: "the distinction *makes sense*"): * Binding: create a name, bind a value to it. * Rebinding: change the value bound to the name. An objection came up that both can be seen as "bind a name to a value". We can nevertheless assume, as there was no further debate on this point, that in most cases and/or for most programmers these actions have a different meaning. Maybe there should be more material to state on that point. I also asserted that these actions are also different at the interpreter level. This proved to be wrong, which someone showed by providing matching bytecodes. [Is this a consequence that namespaces are implemented as dicts? I cannot imagine, at the underlying level, how adding an entry to a hash table can be the same as changing an entry's value.] Among possible advantages of the distinction counts the detection of name spelling errors by throwing NameError (or AttributeError): thus avoiding both erroneous rebinding of an existing name and erroneous creation of a new name. There was few comment on this point, too. Maybe it does not seem important or, on the contrary, you consider it relevant but obvious enough. I also expressed the idea that explicit rebinding is so helpful that it may even avoid the need for 'global' and 'nonlocal' declarations. There was some debate about that point, mostly supporting the idea (right?), but also some opposition. Some talks took place around several coding situations. for item in container: name = <some value dependant on item> <further process using name> The temporary/utility variables in loops revealed a related topic, namely the absence of loop local scopes in python. This launched a short specific debate: there is clearly a need for that, but then it becomes unclear how to later access a value computed in the loop. [There were threads around this on python lists.] if condition: name = value do_something(name) name = value do_something_else(name) In the case of a value that has similar meaning and similar use, both in standard flow and a conditioned branch, it is legitimate to use a unique name. I objected that if a case is special, then the name should be, too. An objection to my objection may be summarized as "naming freedom" ;-) name = ... name = ... name = ... In this state of mind, the above code is perfectly acceptable. Anyway, this is not really an issue, as it can be simply expressed in the frame of binding/rebinding by using the rebinding syntax in following assignments. (Actually, this would even help legibility when assignments are not directly in a row.) Finally, there was a dense exchange launched by the assumtion that most languages, especially the most used ones, do not allow such a distinction. Which is obviously True (which should not mean Good for pythonists, as shown by the syntactic use of indentation ;-). Marcin enlarged the debate by opposing (name) introduction to rebinding instead: this one distinction is indeed allowed and even enforced by most prominent languages, namely C and successors. I find this observation highly pertinent. My personal conclusion derives from Marcin's note: Python was designed to be familiar to C programmers (stated by Guido), adopted its assignment syntax, but got rid of any kind of declaration. As a consequence, there is only one form of name binding left. Languages that have explicit name introduction, with or without implicit default binding, do not need to distinguish rebinding. My point of view is now that declaration free languages like python would better have it; either enforced, or only allowed. Or else we lose all the conceptual and syntactic benefits of such a distinction. Denis [Please erase the debate synhesis if ever you reply to the conclusion only.] ------ la vida e estranya

On Sat, Feb 7, 2009 at 4:31 AM, spir <denis.spir@free.fr> wrote:
Please don't assume. Just because people don't state their disagreements does not mean they agree. I found the statement that binding and rebinding are "obviously" different to be clearly NOT obvious and not a particularly practical distinction and really not worth discussing. I only respond to this to prevent the meme that "everyone agrees" with this from propagating. There *is* something in Python related to this that I find obviously different and that's local and global variables. I would prefer that all global variables have to be included in a global declaration. I dislike the fact that an assignment to a variable changes other references to that same name from local to global references. This sort of feels like "spooky action at a distance" to me. --- Bruce

On Fri, Feb 06, 2009, spir wrote:
Yup, I do that all the time. I happen to like that style. Your proposal would break existing code, therefore it's not going to happen. (Keep in mind that even the 2.x to 3.x transition changed very little of Python's semantic model.) -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.

spir wrote:
Python has several name-binding statements other that assignment. 1. augmented assignments 2. for loops (mentioned by Mark already) 3. import statements (several variations) 4. class statements 5. def statements Any proposal to adjust one should uniformly adjust all. All binding statements currently have the same meaning: if name is currently bound: unbind it bind it to the indicated object If not currently bound, the unbind step is obviously skipped. Simple to understand. Requiring the programmer to indicate whether the unbind step *must* be done or not makes more work and pain for the programmer. It will make certain editing operations much harder by increasing the context sensitivity of code. Suppose I see code like the following: x = (a*a + b*b) / (1 - a*a - b*b) and I realize I can improve efficiency by pulling out the subexpression: tem = a*a + b*b x = tem / (1 - tem) Under this proposal, I would have to care whether tem had been (irrelevantly) used before or not and write the above differently depending on which. Similarly I would also have to care if tem were (irrelevantly) used after and possibly revise the later code depending on whether it were also used previously. What a bother! This will make for more new bugs than the proposal might eliminate. There really is some virtue to the simple-minded design most languages use. Terry Jan Reedy

spir wrote:
I like the idea. On the global/nonlocal thing, it would be possible that a nested function does a:=l and there is both a nonlocal "a" and a global "a". The current global/nonlocal mechanism allows the programmer to disambiguate this case. But it is hard to imagine use cases where this couldn't be resolved by renaming one of the "a" variables. And the same problem occurs in the current mechanism where a function nested 2 levels down has two nonlocal "a" variables: in its direct parent, and in its grandparent. -bruce

On Thu, Feb 5, 2009 at 1:22 PM, spir <denis.spir@free.fr> wrote:
How would you write code like: my_result = [] for item in items: a = <some intermediate result computed from item> ... my_result.append(<something computed from a>) where a is bound for the first time on the first iteration of the loop, and rebound on all subsequent iterations? Mark

On Thu, Feb 5, 2009 at 17:12, Mark Dickinson <dickinsm@gmail.com> wrote:
It would be bound locally to the body of the loop. -- Marcin Kowalczyk qrczak@knm.org.pl http://qrnik.knm.org.pl/~qrczak/

On Thu, Feb 5, 2009 at 5:22 AM, spir <denis.spir@free.fr> wrote:
It was proposed and rejected for Python 3000, so it's unlikely (though not impossible) to be changed. See PEP 3099 (http://www.python.org/dev/peps/pep-3099/ : "There will be no alternative binding operators such as :=") and http://mail.python.org/pipermail/python-dev/2006-July/066995.html I haven't read the thread to see what the reasoning was, but I trust Guido's judgement, Cheers, Chris -- Follow the path of the Iguana... http://rebertia.com

spir <denis.spir@free.fr> writes:
* Binding: create a name, bind a value to it. * Rebinding: change the value bound to the name.
That's not obvious. The semantics could just as well be described as: * Binding: bind this name to that value. * Rebinding: bind this name to that value. If I claimed this semantic description as “obvious”, I'd be just as wrong to do so. But this description functions very well to explain the semantics of these operations for me and others.
Since I see no sense in the distinction, I see the drawback of unnecessarily complicating the syntax. -- \ “I went to a garage sale. ‘How much for the garage?’ ‘It's not | `\ for sale.’” —Steven Wright | _o__) | Ben Finney

Le Fri, 06 Feb 2009 08:31:58 +1100, Ben Finney <ben+python@benfinney.id.au> a écrit :
You are right do describe it like that. I agree that the point of view is not wrong. However, * At the interpreter level, as far as I know, rebinding does not create the name like if it was unknown. (Note that a similar issue happens with dicts.) * At the programmer level, changing the value associated to a name is really a different action than introducing and giving an initial value to a new symbol. For me, *this* is the relevant point: even if the language would behave "behind the scene" the same way in both cases. This is implantation concern. A pertinent objection has been raised already in the case of loops: for item in container: # temp symbol foo = func(item) # process do_stuff Conceptually, there is a foo for each item. Obviously, we cannot express that properly, because the loop's body is the same for each iteration. The issue here lies in the fact that a loop does not introduce a local namespace, while this is precisely what we *mean* when defining such as utility variable as foo. In other words: there is a distortion between language semantics and modelizing semantics. Denis ------ la vida e estranya

spir wrote:
Both binding and rebinding actions are identical.
Whatever implementation difference there may be is transparent at the interpreter level.
* At the programmer level, changing the value associated to a name is really a different action than introducing and giving an initial value to a new symbol. For me, *this* is the relevant point: even if the language would behave "behind the scene" the same way in both cases. This is implantation concern.
I disagree. At the programmer level, x=5 is the same thing whether x already exists or not.
Speak for yourself. When I use a for loop, I do not expect or want it to create a new namespace.
In other words: there is a distortion between language semantics and modelizing semantics.
I disagree. I think the language semantics match precisely the semantics of name binding as I expect it. -- Steven

spir wrote:
Hello,
I wonder why there is no difference in syntax between binding and rebinding. Obviously, the semantics is not at all the same, for humans as well as for the interpreter:
Denis, as you can see from the above line, your email breaks the Internet standard of using hard-line breaks within paragraphs. This causes problems for other people. Please set your mail client to wrap text at 68, 70 or 72 characters.
In Python, names are stored in namespaces, which are implemented as dictionaries. There is a nice correspondence between the syntax of namespaces and of dicts: x = 1 # create a new name and bind it to 1 x = 2 # rebind name to 2 del x # delete name mydict['x'] = 1 # create new key and bind it to 1 mydict['x'] = 2 # rebind key to 2 del mydict['x'] # delete key Also, your suggestion is conceptually the same as requiring declarations: x = 1 # declare x with value 1 x := 2 # assign to x Finally, what should we do here? if flag: x = 2 print foo(x) x = 3 # is this a rebinding or a new binding? print bar(x) -- Steven

Le Fri, 06 Feb 2009 08:51:14 +1100, Steven D'Aprano <steve@pearwood.info> a écrit :
Good point, yes, this holds for dicts, too! mydict['x'] := bar # ==> KeyError: mydict['x'] does not exist. mydict['x'] = 1 # create new key and bind it to 1 mydict['x'] := 2 # (syntax suggestion) rebind key to 2 mydict['x'] = foo # ==> KeyError: mydict['x'] already exists.
Hem... well, you can actually see it like that. The main difference is that, unlike in "declarative" languages, there is no declaration without binding. var foo; int i # not in python So that I would rather call that 'initialization' (== declaration + first binding) as opposed to 'rebinding'.
Interesting, thank you. Now comes on stage the naming problem. What is here expressed is an optional additional step, right? This is written as a special case where whatever is symbolized with 'x' will take a specific value. Later the program enters back the main flow and this thing will have a standard value. I assert that the same name should not be used for both special and standard cases. This imo shows a lack of distinction. Using a different name will make things clearer: if flag: # 'flag' expresses a special case flag_x = 2 # possibly reuse the case name as prefix print foo(flag_x) x = 3 # is this a rebinding or a new binding? print bar(x) I am rather sure that in any concrete model, once the distinction is made clear, then obvious naming can be found. if ambiguity: ambiguity_message = 'ambiguity warning: "%s"\n' % ambiguous_expr print warning_format(message) message = "\t%s\n" % line_body print standard_format(message) Probably most name rebindings rather express a lack of distinction that makes the code obscure. Haven't you ever read things like: config = "config.txt" # string: name config = open(config) # file object config = config.read() # string: content config = config.lines() # array of strings config = parse(config) # e.g. custom object Denis ------ la vida e estranya

spir wrote:
I assert that once you've gotten to the point of suggesting that people change the way they program, you've lost the debate. :) "Practicality beats purity." How many other languages support this split between binding and rebinding? How many of them are popular? (What's the highest rank that one of them has on, say, http://www.tiobe.com/content/paperinfo/tpci/index.html ?) (Don't take this to mean that I disagree with you. I think that if people either had to say when they were rebinding names, or couldn't rebind names (a la Erlang), programs would probably be more stable. But Python isn't the kind of language to do that sort of thing in. I feel it would fit in better with a more academic language like Haskell or Scheme.)
I don't see that code as particularly obscure. Sure you could re-write it to use a billion different temporary variables (but you'ld better make sure they didn't conflict with ones above you!), but that doesn't really help anything from my point of view, and this example (with the addition of some extra syntax) would still be legal in the rebinding-version of Python you're suggesting. Later, Blake.

On Fri, Feb 6, 2009 at 15:38, Blake Winton <bwinton@latte.ca> wrote:
1. Java - split 2. C - split 3. C++ - split 4. (Visual) Basic - split 5. PHP - not split 6. C# - split 7. Python - not split 8. Perl - split 9. JavaScript - split 10. Delphi - split 11. Ruby - not split -- Marcin Kowalczyk qrczak@knm.org.pl http://qrnik.knm.org.pl/~qrczak/

Marcin 'Qrczak' Kowalczyk wrote:
Are you counting the implicit lack of a binding as a binding? "int x;" does not bind anything to "x", technically the first time "x = ..." appears is the first binding. Maybe I am splitting hairs, but this whole topic is a hair splitter.
In addition to the debate above, the declarations are optional in these languages, and in that case, they are very much the same semantics as Python.
With regard to *all* of these languages there is *not* a separate assignment operator, only possibly a special statement (which in none of these languages *require* the initial assignment). And since the debate is about a special operator and not a special statement, all of these languages support dropping this discussion. It really is that foreign. -- Scott Dial scott@scottdial.com scodial@cs.indiana.edu

On Fri, Feb 6, 2009 at 11:43 AM, Scott Dial <scott+python-ideas@scottdial.com> wrote:
Java and C# will always bind a default value on the declaration (even without the "="); C++ sometimes does, and C never does (at least not according to whichever standard I vaguely remember). But there's not really any point in discussing this as a language feature independently of scoping, and none of these languages have scoping semantics that are a good match for Python. -- Curt Hagenlocher curt@hagenlocher.org

On Fri, Feb 6, 2009 at 20:43, Scott Dial <scott+python-ideas@scottdial.com> wrote:
I am treating as "split" languages which distinguish introducing a new variable in the current scope from assignment to an existing variable. Or, in other words, languages where assignment alone cannot be used to create a new local variable. When a variable is introduced, its value can be given explicitly, or it can be assumed to be some default (possibly depending on the type), or it can be unspecified, or it can require further rebinding. Usually there is a choice between the first and some of the others. I do not consider these differences.
"int x;" does not bind anything to "x",
It creates an object of type int and binds the name x to it. The object initially has an unspecified value, and can have its value changed. The association between usages of x in this scope and this object cannot be changed.
In Perl you can assign to an non-existing variable, which is in this case assumed to be global (and you get a warning if warnings are turned on). In non-trivial programs they are local variables which matter. For JavaScript: http://www.webdevelopersnotes.com/tutorials/javascript/global_local_variable... For Visual Basic: http://msdn.microsoft.com/en-us/library/1t0wsc67(VS.80).aspx For Delphi: http://delphi.about.com/od/beginners/l/aa060899.htm All these languages have a syntax for introducing a variable, distinct from assignment to an existing variable, and that syntax is needed for creating a local variable in a function scope. -- Marcin Kowalczyk qrczak@knm.org.pl http://qrnik.knm.org.pl/~qrczak/

Le Fri, 6 Feb 2009 21:47:26 +0100, "Marcin 'Qrczak' Kowalczyk" <qrczak@knm.org.pl> a écrit :
You are thus enlarging the topic to languages where it is possible to introduce a name without any *explicit* binding. As the title of the thread shows, this was not my initial intention, but I must recognize this is pertinent -- see bottom of the message. This debate has proved fruitful I guess, thank you very much. Maybe it's time to close it as probably we have explored the topic enough and this aspect of python will not change in a previsible future. I will try sum up fairly the main discussion points -- feel free to criticize ;-). My startup assertion was that (first) binding and rebinding are conceptually different actions, worth beeing distinguished in syntax (I wrote: "the distinction *makes sense*"): * Binding: create a name, bind a value to it. * Rebinding: change the value bound to the name. An objection came up that both can be seen as "bind a name to a value". We can nevertheless assume, as there was no further debate on this point, that in most cases and/or for most programmers these actions have a different meaning. Maybe there should be more material to state on that point. I also asserted that these actions are also different at the interpreter level. This proved to be wrong, which someone showed by providing matching bytecodes. [Is this a consequence that namespaces are implemented as dicts? I cannot imagine, at the underlying level, how adding an entry to a hash table can be the same as changing an entry's value.] Among possible advantages of the distinction counts the detection of name spelling errors by throwing NameError (or AttributeError): thus avoiding both erroneous rebinding of an existing name and erroneous creation of a new name. There was few comment on this point, too. Maybe it does not seem important or, on the contrary, you consider it relevant but obvious enough. I also expressed the idea that explicit rebinding is so helpful that it may even avoid the need for 'global' and 'nonlocal' declarations. There was some debate about that point, mostly supporting the idea (right?), but also some opposition. Some talks took place around several coding situations. for item in container: name = <some value dependant on item> <further process using name> The temporary/utility variables in loops revealed a related topic, namely the absence of loop local scopes in python. This launched a short specific debate: there is clearly a need for that, but then it becomes unclear how to later access a value computed in the loop. [There were threads around this on python lists.] if condition: name = value do_something(name) name = value do_something_else(name) In the case of a value that has similar meaning and similar use, both in standard flow and a conditioned branch, it is legitimate to use a unique name. I objected that if a case is special, then the name should be, too. An objection to my objection may be summarized as "naming freedom" ;-) name = ... name = ... name = ... In this state of mind, the above code is perfectly acceptable. Anyway, this is not really an issue, as it can be simply expressed in the frame of binding/rebinding by using the rebinding syntax in following assignments. (Actually, this would even help legibility when assignments are not directly in a row.) Finally, there was a dense exchange launched by the assumtion that most languages, especially the most used ones, do not allow such a distinction. Which is obviously True (which should not mean Good for pythonists, as shown by the syntactic use of indentation ;-). Marcin enlarged the debate by opposing (name) introduction to rebinding instead: this one distinction is indeed allowed and even enforced by most prominent languages, namely C and successors. I find this observation highly pertinent. My personal conclusion derives from Marcin's note: Python was designed to be familiar to C programmers (stated by Guido), adopted its assignment syntax, but got rid of any kind of declaration. As a consequence, there is only one form of name binding left. Languages that have explicit name introduction, with or without implicit default binding, do not need to distinguish rebinding. My point of view is now that declaration free languages like python would better have it; either enforced, or only allowed. Or else we lose all the conceptual and syntactic benefits of such a distinction. Denis [Please erase the debate synhesis if ever you reply to the conclusion only.] ------ la vida e estranya

On Sat, Feb 7, 2009 at 4:31 AM, spir <denis.spir@free.fr> wrote:
Please don't assume. Just because people don't state their disagreements does not mean they agree. I found the statement that binding and rebinding are "obviously" different to be clearly NOT obvious and not a particularly practical distinction and really not worth discussing. I only respond to this to prevent the meme that "everyone agrees" with this from propagating. There *is* something in Python related to this that I find obviously different and that's local and global variables. I would prefer that all global variables have to be included in a global declaration. I dislike the fact that an assignment to a variable changes other references to that same name from local to global references. This sort of feels like "spooky action at a distance" to me. --- Bruce

On Fri, Feb 06, 2009, spir wrote:
Yup, I do that all the time. I happen to like that style. Your proposal would break existing code, therefore it's not going to happen. (Keep in mind that even the 2.x to 3.x transition changed very little of Python's semantic model.) -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.

spir wrote:
Python has several name-binding statements other that assignment. 1. augmented assignments 2. for loops (mentioned by Mark already) 3. import statements (several variations) 4. class statements 5. def statements Any proposal to adjust one should uniformly adjust all. All binding statements currently have the same meaning: if name is currently bound: unbind it bind it to the indicated object If not currently bound, the unbind step is obviously skipped. Simple to understand. Requiring the programmer to indicate whether the unbind step *must* be done or not makes more work and pain for the programmer. It will make certain editing operations much harder by increasing the context sensitivity of code. Suppose I see code like the following: x = (a*a + b*b) / (1 - a*a - b*b) and I realize I can improve efficiency by pulling out the subexpression: tem = a*a + b*b x = tem / (1 - tem) Under this proposal, I would have to care whether tem had been (irrelevantly) used before or not and write the above differently depending on which. Similarly I would also have to care if tem were (irrelevantly) used after and possibly revise the later code depending on whether it were also used previously. What a bother! This will make for more new bugs than the proposal might eliminate. There really is some virtue to the simple-minded design most languages use. Terry Jan Reedy
participants (15)
-
Aahz
-
Arnaud Delobelle
-
Ben Finney
-
Blake Winton
-
Bruce Frederiksen
-
Bruce Leban
-
Chris Rebert
-
Curt Hagenlocher
-
Greg Ewing
-
Marcin 'Qrczak' Kowalczyk
-
Mark Dickinson
-
Scott Dial
-
spir
-
Steven D'Aprano
-
Terry Reedy