7
$\begingroup$

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)

$\endgroup$
  • $\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
  • $\begingroup$ A rust-y look may help : medium.com/@vikram.fugro/mutable-reference-in-rust-995320366e22 (not so much in answering the question but in saying that some language (designers) take this question v seriously) $\endgroup$ – Rusi Sep 23 at 7:39
5
$\begingroup$

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 | |
$\endgroup$
4
$\begingroup$

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 | |
$\endgroup$
  • 2
    $\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
  • 1
    $\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
4
$\begingroup$

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
20 IF x = 33 THEN GOTO BLABLABLA

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 | |
$\endgroup$
  • 3
    $\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
4
$\begingroup$

The fundamental element of a computer is a memory cell, which we often refer to as a variable. But what is most important about it is that it can instantly take a new value by being given an electrical input. This is the thing to know, and without knowing that, you know nothing about computers. This is the thing that is a unique feature, different from any other machine or natural object.

When we compare memory cells to math, we are making a huge mistake. The word 'variable' was a mistaken term. It distorts and hides the reality of this marvelous thing, a device which can take new values. The metaphor has led us all in to a ditch.

If you did not ask yourself when you first heard about a computer, "How could such a thing possibly work?" then you need to go back and ask yourself that question now. Without wondering about that and solving it for yourself, you don't really know why a computer is so singular and ultimately different from every other thing, and why it will be able to do the things the brain can do someday. Only a brain is a brain, in all the universe, and only a computer is a computer. This is wondrous.

Let's not hide that from students. Reveal it right away. It is not 'difficult' if you simply tell them the truth. But you have to know the truth first. If you are not still amazed, you have not understood.

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Agreed. Traditional mathematics tends to conflate assignment with variable declaration (which also tends to follow a pattern of so-called "static single assignment"), and also to use the equals symbol to assert an equivalence. Meanwhile, on the computer science side, variables often are assigned separately from their declaration, and may be reassigned multiple times. To confound things further, the equals symbol is often used to test for equality, as well as to perform assignment, and the algebraic properties (such as commutativity) of each use are not the same. (1/2) $\endgroup$ – Steve Sep 15 at 19:01
  • $\begingroup$ I would refer to these two operations as the CopyFrom and the SameAs operators. A further interesting property of the CopyFrom operator, is that the left operand cannot be substituted with its value - rather, it represents the target of the value on the right, in a copying operation. Typically, this means that the address of the variable on the left is implicitly taken and then passed as the left operand value, whilst the variable or expression on the right is evaluated as normal. This is all utterly alien to traditional mathematics. (2/2). $\endgroup$ – Steve Sep 15 at 19:12
2
$\begingroup$

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 | |
$\endgroup$
1
$\begingroup$

Assignment is bad

This is basically the functional language position. And much of Backus landmark Turing award remains relevant nearly 50 years on.
We could rehash those arguments if we wish; but it's good to have something like the Backus TAL as a point of departure for that.

Mutation

Mutation often looks like assignment but is worse

A small Python session showing

  • no assignment
  • assignment,
  • mutating function
  • mutating assignment

Session

 # Functional behavior; no assignment/mutation no problems
>>> a = [1,2,3]
>>> c = [a,a]
>>> c
[[1, 2, 3], [1, 2, 3]]
>>> a+[4]
[1, 2, 3, 4]
>>> c
[[1, 2, 3], [1, 2, 3]] # unchanged

# Assignment; but still harmless
>>> a =[1,2,3]
>>> c = [a,a]
>>> c
[[1, 2, 3], [1, 2, 3]]
>>> a = a + [4]
>>> a
[1, 2, 3, 4] # changed as expected 
>>> c
[[1, 2, 3], [1, 2, 3]] #unchanged as expected 
>>>

#append looks like + but it actually mutates
>>> a = [1,2,3]
>>> c = [a,a]
>>> c
[[1, 2, 3], [1, 2, 3]]
>>> c[0].append(4)
>>> c
[[1, 2, 3, 4], [1, 2, 3, 4]]
# Note how changing c[0] changed c[1]
# ie the unholy alliance between aliasing&mutation

>>> d = [[1,2,3] for i in [1,2]]
>>> d
# A d which looks just like c
[[1, 2, 3], [1, 2, 3]]
>>> d[0].append(4)
>>> d
[[1, 2, 3, 4], [1, 2, 3]]
# But changing c[0] doesn't change c[1]
# ie different aliasing


>>> a = [1,2,3]
>>> c = [a,a]
>>> a[:] = [4,5] # mutation note the ':'
>>> c
[[4, 5], [4, 5]]  # WHAZZAT! 

What do I recommend

1st choice

Use a language like Haskell -- no assignment, no mutation.
Or at least Scheme/ML where these are mostly not used

2nd choice

Use a language like Python as a "functional assembly language".
ie Use it like a functional language; don't teach mention append/extend etc the mutating methods. When some smart Alec comes up using these break his code in the above paradigm!

This is what I often end up doing.

3rd choice

Teach all the mess and confuse the students

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Programming is confusing and it is a big responsibility, like driving a car or dealing with finances. Someday, we will not have those things anymore, but for now we do. Hiding stuff from people does nothing to help them learn and grow. Teach the two hard things immediately and get them nailed down flat from the very beginning. $\endgroup$ – Scott Rowe Sep 28 at 12:05
  • $\begingroup$ Well we'll have agree to disagree on that @Scottrowe😀 We're in 2020. Quite apart from the fact that functional P is now no more ivory-tower : eg clojure, scala, erlang etc, even mainstream imperative/OO are changing course See this microsoft doc Note the "note" «Better to use immutable value types.» What is this other than «Try to program functionally when possible?» docs.microsoft.com/en-us/dotnet/csharp/language-reference/… $\endgroup$ – Rusi Sep 28 at 13:44
  • $\begingroup$ Python portfolio of examples could be extended with a += [4] (mutation) $\endgroup$ – Aivar Paalberg Sep 29 at 8:20
  • 1
    $\begingroup$ @aivaarpaalberg yeah sure: "a = a + [4]" assigns to a whereas "a += [4]" mutates a. There are zillions (OK dozens 😆) of such gotchas waiting the unwary. So what's the point you're making? I'm not sure. My point was (1) to answer why mutation is a problem (2) and worse than assignmentt. eg the well-known mutable default args is (from a pragmatic pov) v important. My point was more philosophic : with all these gotchas why are we teaching? And what exactly are we teaching? $\endgroup$ – Rusi Sep 29 at 8:59
  • $\begingroup$ @ScottRowe thinks these things important. I don't. Not sure where you (aivaarpaalberg) stand on this. And hey that's fine😅 There's 7 billion of us on this spinning rock! $\endgroup$ – Rusi Sep 29 at 9:05

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.