Saturday, May 21, 2005

N = N + 1

When first learning about programming, most people get confused by expressions like
N = N + 1
The origin of the confusion is easy to understand. Expressions like
N = N + 1 often occurs in a computer program dealing with mathematical concepts. And, in mathematics, the expression
N = N + 1
is just plain wrong. Ergo the confusion. To get around the confusion, some programming language introduce a different symbol for "variable assignment". Something like ":=" , or "<--" can be used for that purpose. Python uses the equality symbol for variable assignments. As a result, beginners are often presented with the baffling N = N + 1 before they have understood enough about the language to grasp quickly what is meant by that expression. I suggest that examples based on a "human language context" as opposed to a traditional "mathematical context" could be more useful to teach the meaning of variable assignment.

1. A little story


John, Pierre and Antonio are three good friends that share a house. John is originally from England, Pierre from France and Antonio from Spain.

One day, John was speaking in English to Pierre. During that conversation, John said the word "once", referring to an event that occurred a single time. Pierre translated this concept in his mind as "une_fois".

>>> once = 1
>>> une_fois = once

>>> print 'once = ', once, ' une_fois = ', une_fois
once = 1 une_fois = 1

Later that day, John was speaking in Spanish to Antonio. He mentioned his favourite number: "once" (11), made up of the same letters as the English word "once".

>>> once = 11

However, the conversation that John is having with Antonio has not changed the meaning of "une_fois" for Pierre.

>>> print 'once = ', once, ' une_fois = ', une_fois
once = 11 une_fois = 1

The various words in human languages are associated with concepts or objects that are independent of the words used to represent them. So, "une_fois" is associated with the number 1, through its association with the word "once". However, "once" is just a word, not an object. So, when "once" takes on a different value later, the concept represented by "une_fois" is unchanged.

2. The meaning of = in Python

In Python the symbol "=" associates a synonym on its left hand side to a concept on its right hand side.

synonym = concept/object

W
ords that are chosen as synonyms, are chosen in a context dependent way. In our later story above, names are chosen based on the "human language context". The same combination of letters can mean two different things in different languages, or even in the same language. I remember a little test a friend of mine did in grad school, showing parts of a newspaper headline to fellow classmates (all science geeks) and asking them to quickly read it aloud. The word "unionized" appeared in the headline. Now, think "labour" and "chemistry" and you will think of two different way of pronouncing this word.

Now, in the typical programming situation, "N+1" represents a mathematical concept. We can give it a (temporary) synonym of our own chosing, depending on the context...

3. Another short story

John makes a groceries shopping list, with two items: "bananas" and "pears". He then tapes it on the fridge door.

>>> groceries = ["bananas", "pears"]
>>> epicerie = groceries
>>> print groceries
['bananas', 'pears']
>>> print epicerie
['bananas', 'pears']
Later that day, Pierre walks by and notices the list too (une liste d'épicerie) which he associates with the word epicerie. Still later that day, John adds "apples" to the list on the fridge door. He notices that Antonio had already bought pears and remembers that they also need oranges. He thus scratches the item "pears" and replace it by "oranges".

>>> groceries.append("apples")
>>> print groceries
['bananas', 'pears', 'apples']

>>> groceries[1]="oranges"
>>> print groceries
['bananas', 'oranges', 'apples']

>>> print epicerie
['bananas', 'oranges', 'apples']
The list has changed throughout the day, but it remains taped to the fridge. When they think about the grocery list, both John and Pierre are referring to the same object in their own language. When that object changes, it changes for both of them in the same way.

4. Yet another short story

John makes a groceries shopping list, with two items: "bananas" and "pears". He then tapes it on the fridge door. Later that day, Pierre walks by and notices the list and decides to make his own copy.
>>> groceries = ["bananas", "pears"]
>>> epicerie = list(groceries)

Still later that day, John adds "apples" to the list on the fridge door. He notices that Antonio had already bought pears and remembers that they also need oranges. He thus scratches the item "pears" and replace it by "oranges".

>>> groceries.append("apples")
>>> groceries[1] = "oranges"
>>> print groceries
['bananas', 'oranges', 'apples']
Pierre's list, however, is unchanged.
>>> print epicerie
['bananas', 'pears']
Let's just hope that Pierre won't go out and buy pears!

5. Conclusion?

Your comments are going to provide a much better conclusion than I could write at this point!

8 comments:

Anonymous said...

Excellent ideas and nicely written article. It's only to hope that our students are at ease with juggling 3-4 human languages aside a new programming one ;-) Not easily achieved, in my experience.

Anonymous said...

When I opened this article the thought in my mind was "= operator hard, can't remember ever being confused by that"
But you succeded to create that confusion by your examples, impressive!

;)

André Roberge said...

Regarding the confusion that I created, according to the last comment (and taking it at face value):

The reality is that for *many* people introduced to computer programming, statements like N=N+1 are confusing. If you read about computer language design and pedagogy, you will find that the problem of using "=" as an assignment operator is often noted. This is why, as I mentioned in the article, some languages use a different symbol (like :=, or a left-arrow) to denote variable assignment.

I suspect that most people that become successful programmer are those who, like you, were not confused by this. I was never confused by it myself (from way back to the old Fortran days ;-) but have since read about this problem faced by many.

Anonymous said...

I'm not a Python programmer (actually not a programmer by profession, more of a systems person) so perhaps you can confirm what I'm getting from this article.

Scalar assignments (like:
une_fois = once
) are assignments by value ('une_fois' takes the value that 'once' has at the time of the assignment and remains unaffected by subsequent assignments to 'once'?

List assignments (like:
epicerie = groceries
) are assignments by reference ('epicerie' as a list changes value when 'groceries' as a list changes value)?

Or should I be thinking of list variables in Python as references to lists, thus the assignment:
epicerie = groceries
is really copying the value of groceries, which is a reference to a list, thus when the list is changed by accessing it through 'groceries' reference, the same list is seen to be changed when accessing it through the 'epicerie' reference?

Confusedly yours,
Bruce

André Roberge said...

Bruce:

First: I am just a hobbyist myself - so take my assertions with a grain of salt :-)

In Python, *everything* is an object.
[As an experiment, try dir(a) to see the methods associated with instance or object "a". For example, dir(1).]

Whereas other language make a difference between assignments "by value" or "by reference", in Python there is essentially (afaik) only one type of assignment.

On the right hand side of the = sign is an object.
On the left hand side is a "reference" to that object. I prefer to use the word "synonym" rather than "reference", to try and break the link between what you have learned from other languages and think of Python by itself.

So, in the first example, "once" is a synonym given to object "1". A further assignement like
une_fois = once
is equivalent to
une_fois = 1
where the "synonym" 'once' has been replaced on the right hand side by the object it "refers" to.

It does not matter whether the object on the right hand side is a scalar, a list or some more complicated object.

Note that '1' is an object that can not change (all numbers are like that).

In the second example, "groceries" and "epicerie" are two 'synonyms' that refer to the same object. Whether you manipulate this object (change its content, since it is not a scalar) through one or the other synonym does not alter the fact that there is only one object that is changed. That object (a list) is a mere container for other objects.

You could take the second example, and add at the end
groceries = 3.
Now, "groceries" has been given another meaning and only "epicerie" remains as a synonym to the list.

Did this help?

André

Simon said...

When i learned programming i used to trip over this all the time, until i realised that

"=" is not "equals"

"=" is "gets"

eg. N=N+1, when i read this i say to myself "N gets N plus 1"

Anonymous said...

Andre said

Scalar assignments (like:
une_fois = once
) are assignments by value

List assignments (like:
epicerie = groceries
) are assignments by reference


No, I don't agree with you!
the assignmenet a=b is the same whatever is b.
In python all asignements are reference.
a is a new name for the object (it now has 2 names a and b).
But there are some object that are mutable (like list, dict ..) and othere that are not.
so when you did a=1, you could chnage the inner value of 1 (int are not mutable)!
A list is mutable, a=[], you can do a.append(1)...

When you did a=b this is the same object (you can see it with "a is b") whatever the type of object.
Every time it is a reference assignement, just mean mutable / not mutable object !

Morever you write:

'une_fois' takes the value that 'once' has at the time of the assignment and remains unaffected by subsequent assignments to 'once'?

It is exacly the same for list !
a=[]
b=a
a.append(1)
a=[]
b is [1] and a is []! so no affectation of the value of b by assignement of a.

I hope it will clear everithing. But it is really important to undersand python as name for object (no assignement like in other language) as you can see withn the NameError exception !

André Roberge said...

Laurent:

For the record, it is "Bruce" that said that Scalar assignments ... are assigned by value. ...

I agree with your statement that
the assignmenet a=b is the same whatever is b.
In python all asignements are reference.


In fact, I wrote, in reply to Bruce:

It does not matter whether the object on the right hand side is a scalar, a list or some more complicated object.
...
On the right hand side of the = sign is an object.
On the left hand side is a "reference" to that object...


Note that I tried to explain things in the simplest possible way (without even touching concepts like mutability), as if I were trying to explain what "=" means to someone who has never done any programming before. Perhaps I oversimplified?