Why do some instructors delay teaching mutation due to considering it to be a more difficult concept? (than functional or recursive concepts, etc.)

It is very likely that, back in the 8-bit PC days, many thousands of 8 to 12 year olds learned to code in Tiny Basic or other "street" BASIC implementations (where there weren't even local variables or other easy recursion or functional semantic support). How could these kids do so if variable mutation was a difficult concept?

Or is the spaghetti code they often produce a result of not really understanding the concept itself? (rather than just the software engineering downsides)

  • $\begingroup$ What types of answers are you hoping to get? Asking "How could these kids do so if variable mutation was a difficult concept?" is a bit like asking how kids learned about XYZ before approach ABC. It's not a yes-or-no thing. $\endgroup$ – Kevin Workman Jul 20 '17 at 22:56
  • 1
    $\begingroup$ Are you asking about mutable v immutable "objects" (i.e. Lists v Strings in Java) or just the fact that a variable can refer to different values at different times (i.e. var v val in Scala, say)? $\endgroup$ – Buffy Jul 21 '17 at 0:05

I personally teach mutation almost immediately. However, I agree with Buffy that more difficult is not really the metric people are using to decide to teach mutation later. It is about giving certain key habits a chance to grow and develop before you get there.

Most people find recursion naturally more difficult than a loop. There is no reason why this must be, and folks who learned recursion first will often find the difficult one to be the standard imperative loop. If you begin a student in a programming world without mutability, what habits will grow?

Certainly recursion will come quite naturally. So will linked lists and trees. And certain sloppy habits will be naturally avoided, such as this balderdash:

System.out.println("You found " + hotdogs + "hotdogs!");
System.out.println("How many glasses of water will you drink?");
hotdogs = myScan.nextInt();

Ultimately, there is a deeper philosophical statement being made by the instructor about which habits they would like to inculcate and foster at the very root of their students' thinking. These patterns of thought, it is presumed, will modify the initial ways that the students approach problems even later in life.

I do not know of any research that backs this up, but, of course, much of what we try to impart to our students is not from research, but from intuition. And, who knows? They might be right about this one.

| improve this answer | |

I'll give a general answer that you need to think about before it really registers. It applies to both the OOP case and the more C-like case.

A program with a high percentage of immutable values is easier to reason about and modify.

Once something gets a value/state in one part of the program it has that state throughout.

So, I'm not sure that "harder to teach or grasp" is the right metric here, but what produces a better program.

Deeply nested selection structures are difficult to grasp because you can't simply point to a place in the code and know what is true and what is false. You have to mentally trace the code to understand what is going on. You can avoid that with immutables, though a few other things are needed for a full picture.

And note that assignment isn't essential for computation. I.e. The lambda calculus is Turing Complete without it. This is the basis of pure functional programming. But the same idea can be applied elsewhere, as well, so this isn't a call to only program in that paradigm.

| improve this answer | |
  • 1
    $\begingroup$ I don't think that Turing completeness argument is valid. The Single Instruction Computer is also Turing complete, but you don't really want to use it as a programming model. $\endgroup$ – user58697 Jul 21 '17 at 0:35
  • $\begingroup$ Nor would you use a TM itself for programming. It was a theoretical point. You don't need to push the idea to its end point for it to be useful. $\endgroup$ – Buffy Jul 21 '17 at 0:38
  • 1
    $\begingroup$ Lambdas are the single most powerful feature, add the ability to add your own words (methods), a few primitives, and a bit of lexing, and you can build the rest of the language (any language). $\endgroup$ – ctrl-alt-delor Jul 21 '17 at 9:08
  • $\begingroup$ I agree with @user58697; this isn't really a valid premise at all. A program in assembly language with 1024 modifiable registers and 3 GB of read-only memory would have a "high percentage of immutable values" and would not be easy to reason about or modify. $\endgroup$ – Wildcard Jul 21 '17 at 23:34
  • 1
    $\begingroup$ To quote Harry Potter: Riddikulus. Why take such an extreme example to try to make a point? $\endgroup$ – Buffy Jul 22 '17 at 0:02

The concept of a variable is not hard in and of itself, but it is the first conceptual hurdle for students.

The problem is that in common usage we use the same symbol for comparison and immutable facts as we use for assignment. By the time we start kids with computer programming they are steeped in algebra where "=" means "is the same as".

1 + 1 = 2
5 - 3 = 2
(x+y)² = x² + 2xy + y²

Being steeped in algebra, when they see this construct:

x = x + 10

They automatically want to reduce it algebraically and solve for x

(x-x) = 10

which reduces to

0 = 10

which is nonsense, and they realize that, and get confused.

When programming most languages use "=" as an assignment, where it should be read as "becomes equal to". Back when I started (in the 8 bit days before PC's), BASIC handled this by requiring the "LET" statement, so it read more like algebra, but the LET keyword was a cue that we were making an assignment.

10 LET X = 10
15 LET X = X + 23

The LET notation was cumbersome, so most dialects of BASIC introduced the "implied let". If you started the statement with a variable, it was implicitly a "LET" statement.

Algol, Pascal, and some other language of the day introduced the ":=" operator (read as "becomes equal to") to keep a distinction between assignment and comparison.

x := 10;
x := x + 23;
if x = 33 then writeln("Bla bla bla");

C and its descendents were created for brevity rather than easy reading. They distinguish assignment from comparison by having the most common operation require the fewest keystrokes. Once you started programming in C, you were already thinking like a programmer rather than like an algebra major.

x = 10;
x += 23;
if (x == 33) fprintf(stdout, "Bla bla bla");

Spaghetti code is often the result of not understanding the problem, although an attempt to treat variables as immutables when it is not appropriate would certainly contribute. Even experienced programmers will create spaghetti code if they don't understand the problem, or if the problem changes sufficiently over time. If you don't believe me, walk into any enterprise shop with custom processes and start reading code.

| improve this answer | |
  • 1
    $\begingroup$ I read your comment as that mutability itself isn't as much a conceptual difficulty, as that the common aliased notation for mutating a variable can be a source of confusion. $\endgroup$ – hotpaw2 Jul 21 '17 at 4:49
  • $\begingroup$ the var = expr notation for assignment was used before Basic. It was explained in the preliminary report of Fortran << [J.W. Backus, H. Herrick and I. Ziller.] Preliminary Report : Specifications for the IBM Mathematical FORmula TRANSlating System, FORTRAN. Programming Research Group, Applied Science Division, International Business Machines Corporation, November 10, 1954, 29 pages. >> archive.computerhistory.org/resources/text/Fortran/… $\endgroup$ – Michel Billaud Jul 25 '17 at 20:42
  • $\begingroup$ Agreed. Basic implemented the LET operator to alleviate the confusion generated by the overloaded use of the = operator. $\endgroup$ – pojo-guy Jul 25 '17 at 20:51

It is not assignment that is confusing, it is mutation. I too grew up in the 1980's programming 8bit ZX-Spectrums, and 32bit Amigas (How far we have come).

But when I watched the Structure and Interpretation of Computer Programs videos. I realised that mutation was mostly bad, and should be avoided. While mutation is a bit confusing (Usually use of =, though a language could use :=) , it does not stop there, it then leads to all sort of bugs, and hard to read code. Even for an expert.

Even though we can write programs with a lot of mutation, I know we can I did, it is better, quicker, to write them with less mutation.

What ever we teach first students will subconsciously believe is the most important.

I also think that selection is over used, except we need it if we use recursion. And we need it latter to process inputs.

Once I realised that any program can be written without mutation, with out selection (except to get out of recursion), and with only two unbounded loops (if you have lambdas and full multiple inheritance), my programs got better. A lot better, nearly bug free.

| improve this answer | |

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.