26
$\begingroup$

Consider the following three uses of equality:

  • In mathematics, the statement $x = x^2$
  • In Python, the statement x = x**2
  • In Python, the expression, x == x**2

The math statement is a constraining assertion restricting x to the set $\{0, 1\}$; the Python assignment always evalutes the right side and assigns to the left side; the Python expression always returns True or False.

When and how should the differences be pointed out to students? Are there examples producing unexpected results that are especially effective in causing students to abandon the idea that these three meanings of equality are equivalent?

$\endgroup$
  • 27
    $\begingroup$ They aren't three meanings of "equality". They are three meanings of the symbol =. Many symbols are used for different meanings, especially in different contexts; this is one of them. For example, joe@yahoo.com and 12 @ $1.25 mean different things though both use the symbol @. The only problem I can see is if an instructor started the misinterpretation by saying that something like R = A + B is an equation or maybe "this means R is equal to A + B" and then later corrected that to explain about variables and assignment. $\endgroup$ – davidbak Jul 2 '17 at 1:14
  • 2
    $\begingroup$ By the way the "The math statement is a constraining assertion restricting x to the set {0,1}" is not accurate. It is correct if we know that x belongs to the set of Integers or the Reals or the Complex numbers. But there are other sets (with a definition of multiplication) where the equation x=x*x has different (less or more) solutions. $\endgroup$ – ypercubeᵀᴹ Jul 2 '17 at 21:17
  • 2
    $\begingroup$ In mathematics, $x=x^2$ is a statement which can be true or false, depending on $x$, quite similarly to your second Python example. $\endgroup$ – Carsten S Jul 2 '17 at 22:51
  • 2
    $\begingroup$ From the point of view of a mathematics teacher, let me say that the equal sign in mathematics has several, context-dependent meanings. Some students do not appreciate the distinctions. Often they only get them only vaguely, somewhat like the way you know the idiom of your native language. But this may be a side issue to teaching programming, but it's not like students are equipped by their mathematical backgrounds with a clear understanding of the equal sign. They're inclined to think it's always the same, which might be a source of the problem here. $\endgroup$ – Michael E2 Jul 3 '17 at 18:53
  • 1
    $\begingroup$ Here is another one: the equal sign used in a Join clause in SQL. $\endgroup$ – user737 Jul 3 '17 at 20:37

13 Answers 13

20
$\begingroup$

I actually cover this idea in my very first lesson in AP Computer Science, because I have found that students find the different uses of = to be confusing, indeed. I run a unit based on Tom Roger's unit, Java Ain't Algebra, and I also talk about it a little here.

I do this right at the beginning because, if mutability is not made explicit, students do not seem to exhibit a total loss of comprehension or ability right away, but rather, very slowly slip further and further behind. They will never be able to articulate what they find confusing about the material, because every piece seems to make sense when looked at in isolation.

The confusion itself stems from simply not realizing that there are articulably different uses of equality in the first place. In my experience, simply pointing it out is actually enough to stem the tide of the confusion. (You gave a perfectly wonderful explanation in the question itself.) Then, two or three more times over the first few weeks of class, I will gently remind them that this equals (some code statement we are examining) is a mutating equals, not the constraining equals of mathematics.

I have not had problems from students in this regard since I began this practice.

$\endgroup$
  • $\begingroup$ "Java ain't Algebra" is the key point. A computer program (at least in the procedural languages you are likely to teach first in CS) is a description of an algorithm, not a collection of mathematical equations. You won't find a cookery recipe that tells you how to make a pizza just by saying "pizza = dough + toppings." Of course an algorithm (or a recipe) may contain logical tests - for example "if (dough == black and smoking) then pizza is overcooked" (!!) $\endgroup$ – alephzero Jul 1 '17 at 19:23
  • $\begingroup$ Selecting as the "answer" because the link to Roger's lesson is helpful, mutating/constraining are nice terms to introduce, and because I think the claim of "early and repeatedly" is correct and backed by your anecdotal data. I do think it should be studied and submitted to a peer reviewed journal, as more systematically collected results might violate our shared intuition and anecdotal observations. Without real data, it feels odd to pick an "answer," but I wager yours is correct, including the insightful observation that confusion is delayed, seeping, and hard for students to pinpoint. $\endgroup$ – Bennett Brown Jul 2 '17 at 5:01
  • $\begingroup$ @BennettBrown While teaching it early is essential this is certainly not a CS problem. The inability to grasp the different uses of "=" even just within mathematics is a huge problem that students struggle with. There are actually quite a few papers written on this (ncbi.nlm.nih.gov/pmc/articles/PMC3374577 jstor.org/stable/30034852 ) $\endgroup$ – DRF Jul 3 '17 at 8:36
  • $\begingroup$ Are you really using "mutating equals" when speaking about "assignment" (or binding in less state loving languages)?? Please don't. I don't have much teaching experience, but I can draw conclusions from the mass of homework questions that get posted on SO: a good amount of them are only due to students not knowing (and thus not searching) for the correct terms. $\endgroup$ – Daniel Jour Jul 5 '17 at 14:40
  • $\begingroup$ That's a good point. :) You may be glad to hear that no, I don't use that term regularly. I might use it (or something similar) one time to draw the distinction we are discussing here, but I do go on to then explain the proper term. :) $\endgroup$ – Ben I. Jul 5 '17 at 14:43
16
$\begingroup$

When I have taught this, I have said that = in programming is just a different thing to = in maths. It's unfortunate that someone (I say "some idiot", you might not want to use such language) decided to re-use = for assignment in programming, but now we are stuck with it.

Programming, while it looks like maths, is more like a series of instructions. x=5 means the action "Give the variable x the value 5".

== is more like maths, in that it x==5 checks if x is 5. However, it is still an instruction, it means "Tell me if x equals 5", while usually in maths x=5 asserts that x is equal 5, rather than checks if it is true.

$\endgroup$
  • 4
    $\begingroup$ Always glad to see more teachers here. Welcome to Computer Science Educators! I hope we hear more from you in the future. $\endgroup$ – Ben I. Jul 1 '17 at 19:32
  • 2
    $\begingroup$ I mean, what is wrong with := ????? $\endgroup$ – Mindwin Jul 1 '17 at 23:08
  • $\begingroup$ Comments are not for extended discussion; this conversation has been moved to chat. $\endgroup$ – thesecretmaster Jul 2 '17 at 16:27
  • 2
    $\begingroup$ I think x=5 as assignment could be read as "x equals 5 from now on". Thus it's actually equals, but the demanding version of it, not constraining one as in math.. $\endgroup$ – Ruslan Jul 3 '17 at 12:57
  • 2
    $\begingroup$ "It's unfortunate that someone decided to re-use = for assignment in programming, but now we are stuck with it." – Not really. = is only used for assignment in some languages, not all of them. In fact, I wouldn't be surprised to find that these languages are a minority. Most Lisps use an alphanumeric identifier for assignment (e.g. def or set), Smalltalk originally used and then switched to := only because was not available in the character sets of the early 1980s, Algol, Jovial, Simula, Pascal, Modula, Oberon, and many others, Beta uses -> and puts the target at the … $\endgroup$ – Jörg W Mittag Jul 4 '17 at 8:07
11
$\begingroup$

If your students are coming from a math background, teach them that in most programming languages, all variables have a hidden subscript on them corresponding to a time/step-number (i.e. they're functions of time), and something like:

$x = x^2$

really means something like:

[Let] $x_{t+1} = x_t^2$

You might clarify that such a rule for $x_{t+1}$ only applies for values of $t$ where the "current position" (another hidden variable; make an analogy with a "program counter" register if you like) in the program is at that statement, and that, implicitly in the absence of any assignment to a variable $v$, $v_{t+1} = v_t$.

$\endgroup$
7
$\begingroup$

I'm going to explore an orthogonal concept that sheds light on the question at hand: What is a variable?

In mathematics a variable is a representative for some value, a name. It may be a name for something we know or don't (abstraction comes in here). In an equation, the variable is sometimes called an "unknown". But that isn't precisely true. An equation is a constraint on which values are appropriate for reference. That is because our typical use of equations is to find solutions (i.e. the set of values for which the constraint is true). The value is only "unknown" if we haven't (or can't) solve the equation. But, in math, a variable is misnamed in that (again, normally - there can be exceptions) the value doesn't "vary". So the math terminology is an historic accident to some extent, not absolute "truth."

In computing, on the other hand, a variable refers to a value (also), but the value referred to CAN change over time (or with context). So in computing a variable varies.

In math a variable refers to something (or a set of somethings) that doesn't change.

In computing a variable can refer to different things as a computation proceeds.

So, in maths = represents a relationship. But in Java = (Pascal :=, somewhere else <-, a favorite of mine to see, but harder to type on most keyboards) represents an action: changing a reference.

And in java == is an imperfect representation of maths =. It is a relationship (has value true or false). (imperfect since, while 1 == 0.2 + 0.2 + 0.2 + 0.2 + 0.2 is true, 2 == 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 + 0.2 is false)

Part of the confusion of some beginning students who "know" some math and are learning computing is that they don't understand the math well enough. So giving them a solid understanding of what $x^2 - 2x + 1 = 0$ means to a mathematician may help.

I think that Ritchie and Thompson just hated Pascal's := (too many keystrokes) and so wanted to simplify it when they created C. But, in their defense, they may have been programming on a card punch where only 80 characters were permitted per card and mistakes were costly (repunch the entire card). Typing one extra character slowed down the programmer too much (unless you were lucky enough to employ a keypunch operator). The issue of thinking speed v typing speed is lessened now, but it doesn't go away. However, it is still true that typing is not what makes programming hard.

It is easy (in java) to illustrate the difference between = and ==. Suppose x and y are boolean variables. Then if(x==y), and if(x=y) are both legal, but very different in effect (unless they are not, of course). Fortunately some modern development environments issue a warning when you try something legal but probably incorrect.

But for the record, there are situations in java where you do need to make an assignment in the "test" of an if or while; doing I/O, for example, where certain conventions require it.

String line = null; 
while ((line = reader.readLine()) != null)
$\endgroup$
  • 1
    $\begingroup$ Re "a variable is a representative for some value" - so is a constant, which is the opposite of a variable. $\endgroup$ – alancalvitti Jul 1 '17 at 21:40
  • $\begingroup$ Yes, of course, @alancalvitti, but as the discussion was about variables, I didn't give a fuller exposition. In some ways a constant is more like a math variable than a variable is, though that might just confuse the situation for students rather than clarify it. $\endgroup$ – Buffy Jul 1 '17 at 21:43
  • $\begingroup$ I think the difference between a variable in algebra and a variable in CS deserves its own question and crows sourcing of ideas about how to clarify the difference for students. $\endgroup$ – Bennett Brown Jul 2 '17 at 4:52
  • $\begingroup$ I actually can't think of any common languages where 3 == 3.0 would evaluate to false. Not that I know every common language, but it can't be all that common, can it?. $\endgroup$ – David Z Jul 2 '17 at 7:04
  • 1
    $\begingroup$ Mistaking rounding error for an issue with the intent of the equivalence operator could cause more confusion. The == means the same as the algebraic =, but the unequaled being reported is a function of rounding error inherent in representing decimal fractions in a binary forum. Like fractions of 9 in base 10, many fractions of 10 are infinitely repeating series in base 2 $\endgroup$ – pojo-guy Jul 2 '17 at 12:32
7
$\begingroup$

When and how should the differences be pointed out to students?

When: As soon as you introduce one of those operators...

On the "how" - I'd try to not beat around the bush, so to speak, but to point out straight away that only because we use the same symbol, they still have completely different meanings.

Are there examples producing unexpected results that are especially effective in causing students to abandon the idea that these three meanings of equality are equivalent?

I'd say it is important to be very clear about the fact that these are not "three equalities".

The = in these three statements are completely different (e.g.: mathematical constraint <=> assignment operation <=> equality expression) and have no particular relationship with each other except for using the same symbol and some vague, indirect and maybe confusing similarities.

That is a great time to introduce related concepts:

  • Operations and expressions are quite different in languages, especially imperative ones. Python is one of the few languages I never touched, but this would be very clear and easy to show in Java, C, Pascal (where expressions and operations are very much separated). A different imperative example would be Ruby, where almost everything is an expression, even "if ... then ... else". Or, in the extreme, you have LISP, where only very, very few things indeed exist which are not expressions. Obviously, you'd have to take whatever languages your pupils know, for that...
  • There is no particular reason to assume that any given symbol used in a programming language needs to have any specific semantics, nor, that every semantic has the same symbol in every language. The designers of the language can more or less do whatever they want (for example . vs. -> for method calls, in different languages, or check out the === operator in Ruby, or =~ in Perl, etc.).
  • Depending on the knowledge of your students, you could add even more uses of the =, e.g. in modern functional languages like Haskell (definition, pattern matching), or in something like Prolog (where equality is complicated on a whole new level). But I guess that's a bit too much if they're concerned with the basics, still. Maybe an addendum for the over-achievers. ;)
$\endgroup$
  • 2
    $\begingroup$ +1 for "There is no particular reason to assume that any given symbol used in a programming language needs to have any specific semantics." Just point them to some of the languages used on the codegolf stackexchage. $\endgroup$ – Sumyrda Jul 2 '17 at 9:41
6
$\begingroup$

All of the below is meant to be thoughts/analogies/illustrations to help explain the difference (meant to be said to students) but in reality, this is all dependent on the level of your students.


The expression x == x**2 in python is a "test" - is it true, or is it not? Much like when defining a set, you have $\{x|x>2\}$ (i.e., x is only included iff $x>2$) - a test to see if something should be included in the set, whereas in python, it is often used to check if something should be done. In this line of reasoning, you could write a program to define a set, expanding on what exactly the mathematical notation means:

if x > 2:
    list.append(x)

In other words, if x > 2 is True then do list.append(x).

On the other hand, the expression x = 5 in python is an "assignment" - this is equal to this, no need for argument. *This is much like in math assigning $x = 5$ or something of the sort. We can later use x to represent 5, much like in an equation $x+5$, given the above definition, we know that the result is $10$, because we are using $x$ to represent $5$. A common analogy is that of the buckets - a bucket has x painted on it and whatever is in the bucket is what x represents.

However, things get more complicated from there - what if x = x**2? Then, you take what x was previously defined as, square it, and then redefine x as equal to the new thing. For example, let's "run" the following program:

x = 5
print(x)
x = x**2
print(x)
x = x**2
print(x)

What will we see? Well, it is quite obvious that the first thing printed is "5"; I doubt there will be much confusion there. Now, the next line is squaring the previous x, i.e., squaring 5 ($5^2$) and then setting that equal to x, so now we basically have the line of code x = 5**2 - which produces 25. All very well and good, now we do the same thing - so we basically have x = 25**2 or 625.

The difference between those two and what they mean is a very useful and important distinction, but to be honest I think it's not completely unintuitive. Once explained the former is a test and the latter a definition, I think students will catch on fairly quickly with a reminder here and there.

Now we come to your last (well, first) type of equality. $x = x^2$ is a statement of definition, but it can also be manipulated. In python x = x**2 is a definition, and it accesses the previous definition of x to "solve" it, like we did above. However, to solve $x = x^2$, we move terms around the equals sign - this is a quadratic, so we get $0 = x^2 - x$ and we can factor out the $x$ so $0 = x(x - 1)$ so using the zero product property one gets $x=0$ or $x=1$. We can solve equations like this in Python, but that's not automatically done when you define x = x**2, instead it uses previous definitions.

I hope that conveys what you are wanting, but I really don't think you need to bring up your first definition of equality - the rules of that have been drummed into them from math class, and the new rules of equality appear distinctly enough that I doubt they will be confused.

Now, all of the above is with a nice, good language like Python. Some other languages have =, ==, and ===. I'm not qualified to get into that, but this might not be valid for such craziness.


As for when this all should be pointed out - the uses for these concepts are so fundamental, this really is almost day 1 (maybe day 2) of class - install/open the IDE/whatever, learn how to print, then start with variables. This is one of the most important things to learn in a language like python - how to use variables and manipulate them to your advantage.

$\endgroup$
  • $\begingroup$ I get what you are trying to say in each sentence but the use of language in this post is so sloppy/fuzzy that it is the sort of writing/presentation that is why students get confused. $\endgroup$ – philipxy Jul 3 at 21:51
5
$\begingroup$

I always introduce programming by saying, "The computer can only do 5 things: fetch from memory, store in to memory, arithmetic, test, and jump (modify the Program Counter)." As it was in the beginning, is now and ever shall be, world without end, Amen, Amen.

Assignment means store in to memory. Equality is a test. Done. I think we need to emphasize how computers actually work right from the beginning, and then these misconceptions never arise.

$\endgroup$
  • $\begingroup$ I assume that you are not in favor of teaching Haskell early, then. $\endgroup$ – Carsten S Jul 3 '17 at 12:40
  • $\begingroup$ I was only saying that because Haskell has no assignments and you do not specify the execution order. $\endgroup$ – Carsten S Jul 3 '17 at 12:51
  • $\begingroup$ This is like saying that all a person can do is vibrate their molecules. $\endgroup$ – philipxy Jul 3 at 21:47
5
$\begingroup$

I don't teach CS in any official capacity but I have tutored a number of friends and colleagues on the basics. I find that differentiating the language I use when describing the different concepts helps a lot, for instance:

  • Mathematical x=x*x = "X equals X squared"
  • Assignment x=x*x = "X is made equal to X squared"
  • Comparison x==x*x= "Test if X is equal to X squared"

Using the above terms when talking through code I have never been asked to explain the difference between assignment and comparison. YMMV

I think this stemmed from the first language I was taught academically was pascal where the assignment operator is := and comparison is =, having that difference caused me to internally narrate my code in this way, which has helped my understanding and my vocabulary when explaining to others.

$\endgroup$
4
$\begingroup$

I've not tried the following, so I'm unable to vouch for their effectiveness, but if you're looking for suggestions:

  • Avoid assigning variables directly (i.e. x = y)
  • Hide the implementation in functions that have semantically clear names (e.g. x.Assign(y) ), although this assumes an object-oriented approach. Something like: x = Int.Create(y) uses assignment but the function may make it less likely to be confused with an equality assertion.
  • Similarly functions can be used to test for equality in favour of ==
  • Use addition assignment: +=, which is behaves as I intuitively expected an assignment to.

Of course the above will only buy you some time before assignment and equality checks need to be explained properly, but it gives the students some time to adapt to programming without being overwhelmed with too many new concepts at once.

Depending on the course it might be appropriate to use languages like J, which uses =:, or f# where the 'let' keyword is used to indicate the = is an assignment (though, possibly confusingly, a single = is also used to test equality).

$\endgroup$
3
$\begingroup$

I would generalise this, because other symbols and terminology are also affected (">" or textual statements such as commands).

Start by explaining that symbols and terms in each language have meanings specific to that language. They may overlap or have similarities, but never assume that just because a symbol or word has some meaning in one language or scenario, that it has the same meaning in another.

Then use "=" as an example of this general rule. This changes "=" from "a problem affecting one situation" into "a classic example of a really important rule that applies to all of computer science" and into a memorable learning point. You can then pick a few other examples if the students need it.

This will prepare them for the idea that different languages often also have different philosophies, approaches to, and ways of representing even superficially similar programming structures.

$\endgroup$
3
$\begingroup$

When introducing = and == in python, I refrain from reading them loud with a name that contains "equal" (or rather « égale » in French).

Instead, I always read x = y as "x takes the value of y" (« x prend la valeur de y » which happens to be literally what the pseudo-language used in earlier classes mandates) and x == y "x has the same value as y" (« x a même valeur que y »).

And this leaves "x equals y" (« x égale y ») for $x=y$ to my math colleagues, which they usually use.

$\endgroup$
2
$\begingroup$

The way I explain it in my lectures is slightly different from what I have read in the other responses. I think there is one important piece of implicit information missing so far: the difference between imperative and declarative programming. Since the difference between the two is hardly ever shown explicitly but is often important to understand what's going on and avoid bugs I focus on that concept early on.

In this case the issue is that the equals sign means something different in declarative code (i.e. the maths statement) and in imperative code (the two python examples).

The mathematical statement "x=x*x" doesn't do anything. It declares a rule that shall be fulfilled by the following calculations, but it doesn't perform any immediate action. It is not fixed to a certain point in time - as soon as you write it down it was practically in existence before anyone performed the first actual calculation. The same applies to declarative code in computer programming. When you declare a new class it simply exists whenever a line of code is run. There is no defined point in time when it is created (unlike imperative construction of object prototypes as in Lua or JavaScript).

The two python lines on the other hand are imperative, they perform an action at the time when they are called. I don't know about Python, but in most languages both operators are actually just shortcuts for a "normal" function definition like

bool operator==(a,b)

so there is a clearly defined order in which the involved expressions are evaluated and there is a clear task to be performed.

Once you know the difference there is basically no room for ambiguity left.

$\endgroup$
1
$\begingroup$

The programmer's x == x**2 is the exact same statement as the mathematics $x=x^2$: it is a statement that can be either True or False. Most people are just rather cavalier in their usage of the mathematics version: They'll just STATE that $x=x^2$ and then derive $x \in \{0,1\}$, but what they are really doing is writing a proof that if the statement $x=x^2$ is True, then the statement $x \in \{0,1\}$ is also True. Notably, the statement $x=x^2$ does NOT simply constrain $x \in \{0,1\}$, since one might very well start out a mathematical argument as "Suppose that $x=x^2$ is False...."

The real difference is in the control structures surrounding the statement. if...then in programming is a control structure, whereas if...then in mathematics is simply another statement that can be either True or False.... i.e. mathematics is generally concerned with the logical implications of $x=x^2$ being either True or False, whereas programmers are generally concerned with the difference of what they will show on a screen when x==x**2 or x!=x**2.

$\endgroup$
  • 1
    $\begingroup$ Welcome to Computer Science Educators! I'm not so sure I agree with you, though, that "The programmer's x == x**2 is the exact same statement as the mathematics $x=x^2$". The first is a test, and the second is an axiomatic constraint. $\endgroup$ – Ben I. Jul 3 '17 at 15:46
  • $\begingroup$ It's not an axiomatic constraint. I can very well stipulate in a mathematics context that $x=x^2$ is False. $\endgroup$ – Scott Jul 3 '17 at 16:19
  • $\begingroup$ For instance, suppose one wants to prove that "If $x \in \{0,1\}$ then $x=x^2$", one could set out to prove the contrapositive: "Suppose that it is not the case that $x=x^2$, then $x^2-x=0$ is False, so $x(x-1)=0$ is False, so $x-1=0$, $x=0$ are False, therefore, $x \in \{0,1\}$ is False." $\endgroup$ – Scott Jul 3 '17 at 16:24
  • $\begingroup$ Disclaimer: I am a mathematics educator, and when I use the statement $x=x^2$, I very much mean that that is a statement that can either be True or it can be False, depending on the value of $x$. $\endgroup$ – Scott Jul 3 '17 at 16:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.