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$
3
  • $\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$ Commented Jul 20, 2017 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
    Commented Jul 21, 2017 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$
    – Rushi
    Commented Sep 23, 2020 at 7:39

6 Answers 6

6
$\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.

$\endgroup$
6
  • $\begingroup$ A lot of the ASP.Net web apps I have created lately don't have any loops in them. Most of the mutation is to update a database with SQL. So I have not seen a reason to use functional or OO approaches. Am I misunderstanding something? $\endgroup$
    – Scott Rowe
    Commented Sep 2, 2021 at 1:34
  • $\begingroup$ @ScottRowe Your programming language is SQL; its used purely functionally when you write only SELECT; its mutable side goes under the UPDATE s. Loops are everywhere and nowhere! Nowhere because you dont see them (like pointers in Java/Python). Everywhere because everything is by default at the relation level. Programming analogies would be broadcasting in numpy or LINQ in .NET.The thing you think of as your programming language — I guess C# — is more like a glue like shell in traditional *nix usage. So what is the question? Heck a + in C or ADD in assembly is a 32/64 bit hardware loop! $\endgroup$
    – Rushi
    Commented Sep 14, 2021 at 6:22
  • $\begingroup$ @Rusi If we think of SQL as a Domain Specific Language, and C# as basically a DSL also (you described it as being like a shell script, which I agree with) then it's already about as optimized as possible in terms of simple, direct code. So I don't see how making it more cryptic or how re-casting it as Functional or OO would add anything useful. It is already good. There is too little there to 'improve' it. What would you do with such a program to convert it to OO or Functional that wouldn't just add more boilerplate or render it incomprehensible? That's what I am asking. Isn't it good as is? $\endgroup$
    – Scott Rowe
    Commented Sep 14, 2021 at 10:24
  • $\begingroup$ @ScottRowe Oh I did not wish to improve this configuration -- others may that's another matter. For me SQL is a damn neat functional language. And all the ORM malarkey comes from a misunderstanding viz. that OO is higher level than SQL. In a sane world OO would be taken as lower-level than SQL! Perhaps the broader framing error in your question is the assumption : Doing FP means using an FPL. I suggest an alternative view: FP as a thinking-strategy not a technology -- like flowcharts were decades ago. See blog.languager.org/2012/10/… for more $\endgroup$
    – Rushi
    Commented Sep 14, 2021 at 12:02
  • $\begingroup$ Analogous to my «SQL is a neat FPL» here is Simon Peyton Jones -- one of the biggest names in FP today -- saying Excel is the worlds most widely used FPL slideshare.net/kfrdbs/peyton-jones $\endgroup$
    – Rushi
    Commented Sep 14, 2021 at 12:13
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.

$\endgroup$
6
  • 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
    Commented Jul 21, 2017 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
    Commented Jul 21, 2017 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$ Commented Jul 21, 2017 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
    Commented Jul 21, 2017 at 23:34
  • 2
    $\begingroup$ To quote Harry Potter: Riddikulus. Why take such an extreme example to try to make a point? $\endgroup$
    – Buffy
    Commented Jul 22, 2017 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.

$\endgroup$
4
  • 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
    Commented Jul 21, 2017 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$ Commented Jul 25, 2017 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
    Commented Jul 25, 2017 at 20:51
  • 2
    $\begingroup$ Some good ideas. However, your dismissal for immutable as it leads to one small problem, is a common fallacy when facing change. Yes, it will not fix all problems. Yes, it can introduce new problems (but fewer). My preference is immutable by default (Give me a mutable keyword, and I am happy. However, don't over use it). $\endgroup$ Commented Aug 31, 2021 at 7:45
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.

$\endgroup$
5
  • 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
    Commented Sep 15, 2020 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
    Commented Sep 15, 2020 at 19:12
  • 1
    $\begingroup$ “Memory cells” is just (one) implementation. However, we are discussing teaching. Teaching research has shown that this model in not the best model for teaching. Outside of teaching, research has show that it is not the best model. It is what we do in assembler/machine-code, but we use compilers to abstract away from this miss, and toward the human. $\endgroup$ Commented Aug 31, 2021 at 7:37
  • $\begingroup$ @ctrl-alt-delor If we are abstracting, shouldn't we be very sure we understand the concrete reality of the system? Is this why we teach arithmetic first, then algebra, then geometry and graphs (functions) then calculus (applications)? Does anyone suggest just starting with calculus? I would like to see the teaching research that you refer to. $\endgroup$
    – Scott Rowe
    Commented Sep 2, 2021 at 1:17
  • 1
    $\begingroup$ @ScottRowe In Computer Science teaching, abstraction is often confused. Both Computer Science and teaching use the word abstraction. However, They are different. That is, they abstract different things. In teaching, we avoid abstracting away from the concrete: what is already known. Keep it human centered. In Computer Science, we abstract away from the hardware, toward the human. So an increase in abstraction in one is a decrease in abstraction in the other. $\endgroup$ Commented Sep 2, 2021 at 5:38
2
$\begingroup$

It is not assignment that is confusing, it is mutation. I too, grew up in the 1980s 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. However, 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 overused, 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, without 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.

Alternatives to full-multiple-inheritance include: (I don't know all the names)

  • Duck-typing
  • Prototype based OO
  • The one in kotlin, where you define interfaces. (it is like specifying the inheritance late)
$\endgroup$
5
  • $\begingroup$ Few languages have full multiple inheritance. Would you please provide a reference that shows the technique you describe? It sounds like something I learned in a Lisp class over 35 years ago, and if I have overlooked it all this time I would like to improve. $\endgroup$
    – Scott Rowe
    Commented Sep 2, 2021 at 1:27
  • 1
    $\begingroup$ @ScottRowe Yes. Many languages are defective. You can do 90% without multiple inheritance. In a language where everything is first-class (e.g. lisp). You can implement foreach. foreach is a bounded loop, but its implementation uses an unbounded loop. The other loop is the super-loop (while user_has_not_chosen_to_exit:) $\endgroup$ Commented Sep 2, 2021 at 5:55
  • 1
    $\begingroup$ I added some alternatives (to the answer) to full-inheritance $\endgroup$ Commented Sep 2, 2021 at 5:55
  • $\begingroup$ I inherited a well-designed system about 30 years ago that is basically your 90% solution. It was written entirely in C, no OO. So, to me, languages are just a convenience, not essential. I decide what I want, and I build it, even if it's difficult. But making it easy doesn't change the design process. If teaching is about teaching design, then languages and approaches matter much less, because they will change, but objectives will not. $\endgroup$
    – Scott Rowe
    Commented Sep 2, 2021 at 9:58
  • 1
    $\begingroup$ @ScottRowe I agree. Unix is written in C and it is an OO design, with (reference-counted) garbage collection. And languages do only make it easier. We should make it easy to do the right thing, but not make it impossible to do the wrong thing: sometimes mutation is the best solution (e.g. implementing a random-number-generator). I think choice of language is important, but also agree that you can write good or bad code in any language. $\endgroup$ Commented Sep 2, 2021 at 15:54
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

$\endgroup$
13
  • 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
    Commented Sep 28, 2020 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$
    – Rushi
    Commented Sep 28, 2020 at 13:44
  • $\begingroup$ Python portfolio of examples could be extended with a += [4] (mutation) $\endgroup$ Commented Sep 29, 2020 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$
    – Rushi
    Commented Sep 29, 2020 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$
    – Rushi
    Commented Sep 29, 2020 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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