Math Relearning/Math Student Simulator/Introduction

From The Thinkulum
Jump to navigation Jump to search


Math Student Simulator is an attempt to use the process of programming to learn certain aspects of math. It's a part of my math relearning project. I'm posting the code and its documentation on GitHub here. You can download and run it yourself for free. I'll update the GitHub content over time as the project progresses. Here on the wiki I'll be documenting some of the process of creating the program.

The program will cover concept definitions and procedures from at least the Common Core standards. If I get through all of those, I might add other areas of math. The structure of the program will be hierarachical. Complex concepts and procedures will be built from simpler ones. This is a key feature, because one of the main characteristics of math I want to explore is its interrelatedness.

In the code for this program I'm striving for clarity, since I'll need to review it so I can learn. For the amount of thought it requires to create, code is distressingly easy to forget, and if you're not careful, it's easy to write it in such an obscure way that, when you reread it weeks after writing it, it takes a lot of work to figure out what it means and does. I expect at least three features to help with review:

  • I'll use generally recognized good coding practices, such as breaking the code up into small, descriptively named functions.
  • I'll have the program show its work as it's executing my mathematical commands. That way I can watch the hierarchy of math as it comes into play during a specific procedure.
  • I'll use literate programming to document my code so I can explain everything in excruciating detail while organizing and formatting my explanations clearly. Literate programming lets you write your program as essentially an article or book with the code interspersed. You then run a processing program that formats your documentation nicely for people to read and assembles the code from your document so that the computer can run it.

Why do I think programming to learn math is a good idea? First let's look at what I've been trying to accomplish and the methods I've been using to achieve it, and then I'll talk about how programming could solve some of the problems I've been having with those methods.


My goals in doing my math relearning project are to relearn (1) standard math topics plus selected others (2) at an accelerated pace, (3) with enough fluency that I can work with math quickly and confidently, and (4) with a deep enough understanding that I can think flexibly about them to solve unfamiliar problems (and deep enough to keep me interested and to quench my unquenchable thirst for understanding). I expect to use math extensively in my future career (probably cognitive science) and in many of my personal projects, and I feel hindered until I can learn the math I need.

Subject matter

In several ways math is a uniquely challenging subject to learn: (1) It's almost entirely concerned with and ruled by logic, which makes its behavior very rigid, precise, and unforgiving, whereas most human minds are sloppy and hazy until they learn discipline. (2) To many people (including me) mathematical concepts feel empty and meaningless, and thus arbitrary, so they don't stick in the mind easily and can take a lot of effort to think about. (3) Math involves a large number of concepts and procedures that are highly interconnected, which can be confusing if you don't take the time to sort them out. This third factor has been my major problem so far in this project, as I'll explain below.

Current methods

Any learning, especially if, like math, it involves developing skills, will require several kinds of learning activities and multiple passes over the material so the information and skills can be processed into long-term memory. See A Framework and Agenda for Memory Improvement for more on that. But if a rapid pace of learning is one of your goals, you have to select your learning activities carefully so you learn adequately without wasting a lot of time. You also have to select your material's degree of breadth and depth carefully, since more of either will take a longer time to learn.

What learning activities have I been trying so far? Mainly I've been reading books and other documents that explain math to teachers so they can pass on the understanding to their students. But since a lot of these documents don't explain things in quite the order and manner I'm looking for, I've been analyzing the content to articulate, separate, and trace the conceptual threads as they develop through the grades. Basically I've been expanding and shaping the content from my sources into a structure that I think will give me the kind of knowledge and skill I need. I've been writing my insights as I go. I did a pass over the whole K-12 curriculum to get an overview and then started over with pre-K to learn in detail. As I've come across procedures I'd like to perform with more fluency, I've come up with exercises I think would help me, since I don't need the kinds of exercises for young children the curriculum offers at the early levels.

What kind of mathematical knowledge structure am I trying to create? It has two broad features: interconnectedness and incremental progression. The interconnectedness feature comes from (1) the idea that math is a set of logically interconnected concepts and procedures, and (2) the idea that our starting point in the development of mathematical thinking is math's relationship with the world, and (3) my goal of understanding math deeply in order to develop my mathematical intuition. This approach has a name: Teaching math in terms of its real-world meaning and its interrelationships is called conceptual math. Its opposite is procedural math, which teaches it primarily as a set of rote procedures.

The second feature, incremental progression, means that ideally I'd like to find out how the whole edifice of mathematics might grow logically from the ground of human experiences and needs. Presumably that's more or less how it developed historically, though many of the details are lost to us. This goal means that each concept would be explained in terms of the more basic concepts that came before it as well as any experiences or needs that suggest the new concept or make it necessary. You'd try to avoid bringing in more advanced concepts to explain it, even if that means only explaining it to a very limited degree at first.

Essentially I want a map, which is a common theme for me. If I need to navigate freely through a domain of knowledge or skill, I feel lost unless I have some kind of mental map that tells me what places are there, the borders of each place, what other places are accessible or inaccessible from it, and ways to get from one place to another. And if the map is in some concrete form so I don't have to rely completely on my shaky memory, I feel even better. Feeling lost looks like, for example, blanking on how to use a piece of knowledge, or worrying that I'll use it wrong because I know I've forgotten related pieces that would probably affect the application. It's not that feeling lost keeps me from knowing things or ever using what I know. I have impartial knowledge of all kinds of subjects, and I still get by. It just nags at me and distracts me with uncertainty, and it would be nice for once in my life to scratch the itch of wanting a well-organized body of knowledge when such a body is clearly available.

Source material


Where would I find such conceptual explanations of math? It turns out education researchers have spent decades coming up with them, and their findings have been condensed into resources I can access, such as Chapin and Johnson's Math Matters. However, I had trouble finding a building block approach to conceptual math until I looked into the Common Core Standards and their associated resources, primarily the Progressions and the EngageNY curriculum. While building up from basic concepts and experiences is the way children are taught math, adults who are being taught to teach math conceptually don't need things explained in such a stepwise fashion because they already have a broad knowledge of math and only need the concepts better integrated. So, for example, the early books I looked at thought nothing of analyzing place value in terms of exponents, even though children need to know something about place value years before they're ready to know anything about exponents. Common Core is focused on how to teach conceptual math to children rather than adults, so its developers were careful to limit their explanations of math concepts to the level of understanding available at each stage. How well they succeeded is a matter of debate, but I think they did well enough for my purposes.

Why do I need to do all this work analyzing and expanding these sources' content? To form a good map, all the necessary information needs to be present, explicit, and direct. My sources don't really share my goal of building a complete mathematical edifice, so their information doesn't always follow this pattern. This was especially true of the pre-Common Core sources. Some of the information I wanted to know was missing, so as I read and tried to fill in my picture of math, I had to answer certain questions myself, such as what is a number? This was fun but took a lot of time, though in the case of defining numbers I was pleased with the results (see Math Relearning/Number Sense). Fortunately, the Common Core sources answered a lot more questions for me.

But then as I began reading EngageNY, I thought it'd be helpful to spell out all the propositional concepts in each module so I could trace the progression of mathematical ideas in a clear and logical order. Many of these propositions were implicit in the source material, since the logical progression I had in mind took very small steps, similar to a proof. And statements in any work are rarely written as directly as I'd like. Spelling these out or rewriting them took only a moderate amount of time, but it still felt like too much considering the amount of uncertainty I felt about the result. More on that in the Notes section below.

Like I said, confusion over math's interconnections has been my major problem. The density of math itself is bad enough, but it's even worse if you're learning math by reading material about how to teach it, which brings in extra, though possibly relevant, concepts about psychology. For example, knowing the mistakes students commonly make is helpful for highlighting various aspects of the correct understanding. But this is a roundabout way of gaining insight, so it takes time to sort out.


If the source material were already in reviewable form, I could just read and reread it to study. But most documents aren't written to be studied just as they are, and the Progressions and curriculum were no exception. It became clear that even familiarizing myself with their explicit content would require some kind of notetaking. I was planning to wait till I read the curriculum to concentrate on the details, but as I read through the Progressions at a moderate, steady pace, I worried that I was going to miss or forget concepts that would help me understand later ones, and with good reason, since it happened even in the middle of the reading I was doing. Especially when I got to fractions, I found myself wanting to flip back to reread earlier explanations so I could put the pieces together in my mind. But when I did flip back, the content looked less like a network of beautifully interlinked concepts and more like a bewildering wall of text. This meant that if I were going to try to learn the details this way, I'd have to spend a lot of time re-deciphering and filtering the text to review. This, to me, highlights the need to visually design complicated material so its complexity is easier to trace at a glance. In other words, prose isn't always the best tool for describing math. So as I pushed myself along, I wondered how to think of the concepts in ways that would help me truly understand and remember them. This added uncertainty and a subtle stress to the project.


A good notetaking method is a central practice in learning, because it transforms your source material into a version you can (1) understand and (2) review. Hence, if you're having trouble taking notes, it's a central problem for your learning.

Since I was only reading the Progressions to give me an idea of what a Common Core curriculum would cover and how it would explain the concepts, my few notes were limited to my reactions to the content. As I mentioned earlier, I took more serious notes when I began reading the EngageNY curriculum. But as I usually do when I'm taking notes, I ran into problems even there. I didn't know how complete or reviewable my notes were. Were they expressed clearly and consistently? I didn't know if I was recording information at the best level of granularity--where did I need to spell things out in detail, and where could I write something more general, wave my hands, and say, "I know what I mean"? And was I including all the information I wanted and not extra pieces I'd have to actively ignore or delete later? I didn't have a great way to decide. I was making up my math notetaking language as I went along, and I didn't know if it was adequate or where it would get too awkward for expressing what I wanted to say. I also didn't know if I'd be wasting time writing particular kinds of notes. Should I spell out algorithms? Write out definitions? If they were already stated clearly in my sources, would it waste more time to copy them or to flip through my documents to find them again for study?

So I've had problems with not only my source material but even with the notes I've been taking to wrangle it. I want to end up with a map of mathematics I can study and use, so the statements that describe it need to be explicit and direct, and it needs to be complete. My sources cover a lot of that ground (and I love them for it), but compared to what I'm looking for, their content still contains gaps, and their prose format makes rapid reviewing difficult. But when I try to lay out this math map in my notes, I find that my idea of what the map should contain and how its contents should be described is unclear. I don't know if I'll find better sources, but I know I need a better way to take notes, and I think I have one.


Programming isn't normally done as a learning activity. It's usually done to create a product, a computer program, that will perform certain functions that the user can trigger to accomplish some result in a particular domain, such as using financial software for money management. If you wanted a product that facilitated learning, you could create, for example, a flashcard program for memorization. When developers do use the actual process of programming to learn, it's usually to learn some aspect of programming, such as a specific programming language, library, or technique. But you can also use programming to learn about a domain. Someone could write a money management program simply to teach themselves how money management works. Some authors write a book to teach themselves about a topic (and in fact, writing this project introduction has helped me work out how programming can aid learning). A programmer can do the same thing by writing a program.

I see two levels of benefit that programming would bring to my math learning. Programming in general has characteristics that make it a fitting vehicle for learning, and this specific project comes with its own opportunities.

General benefits

Programming has three main abilities that assist learning: aiding thought, settling emotions, and granting freedom. These abilities derive from some of the fundamental traits of programming itself and of the culture surrounding it. I'll talk about these traits first and then the benefits they enable.

Basic characteristics

Programming has two main features that let it work as a learning approach. First, it's a linguistic activity that's broad enough to express practically anything you want to say. This means you can model almost anything you can think of with a computer program, and the description of this model in the form of code acts as its map. Programming's linguistic nature also comes with the ability to record these expressions for the computer to recall later.

Second, it's executable, so the computer can act on your model in some way to produce some result. The execution of a computer program is based on logic, which comes with a number of benefits that I'll explore below, such as the ability to automatically check your work for accuracy. It's also what I'd call passive execution, because on its own the computer can't reason about its instructions and make decisions about them the way a human can, which means, among other things, you have to think more carefully about the instructions you're giving it. To highlight these two overarching features, you could call programming a means of executable expression.

On top of the features of programming itself, the culture of software development has at least one feature that shapes programming into an effective tool for learning, and that is its concern for efficiency. In addition to writing fast programs that conserve computer memory, developers try to minimize the amount of time, effort, money, and customer good will they spend on fixing errors in their programs and creating new features. So they look for programming practices that will avoid introducing errors and make their code easier to work with. For instance, when their program needs to do the same thing in more than one place, instead of duplicating the code, they name parts of their code and simply refer to those parts by name. That way they only have to make changes to one copy of the code (because there is only one copy), so they don't have to worry whether they've changed the copies consistently. This attention to efficiency results in various patterns that can aid learning, such as the growth of interacting software objects that can serve as pieces of your domain model.

These characteristics of programming and software development lead to the benefits of sharpening thought, allowing freedom of movement, and providing emotional security.


As a means of executable expression, programming sharpens thought. For me, this is the main attraction of programming as an approach to learning. It crystallizes an understanding of the subject matter from the vaporous notions you start with. It does this by narrowing focus, clarifying vagueness, and enforcing logic.


Programming narrows focus. In keeping with the developer's concern for efficiency, most of the time when you're writing a program, you're focused on functionality, instructing the computer to carry out the procedures that are part of the program, which will have at least somewhat defined parameters. You could, by contrast, tell the program to do a collection of unrelated things and decorate your code with irrelevant information, but the general expectation in software development is that your code will efficiently express instructions to carry out a fairly narrow range of related tasks. After you've been programming a while, you develop an intuitive sense of the kind of information in a situation that's relevant to creating functionality in a program, and specifically in the kind of program you want to create. It's like solving a word problem in math, or better, using math to solve problems in real life. You pick out the mathematically relevant information and put it together to find the information you're missing. So as I'm reading my source material, keeping my program in mind can tell me what information to include and what to ignore, at least until later.

Math clearly benefits from a focus on functionality, since you could say half of mathematical activity is calculation, a purely algorithmic endeavor. The other half is creative problem solving, which is harder to condense into a specific procedure. So you can capture a lot of mathematical knowledge in a program, and a lot of the program's functionality will be a representation of that knowledge, the content you're out to learn. Aside from whatever you write in the documentation, the code represents the domain's content in a stripped-down form, so you don't have to wade through a lot of extra verbiage to get to the essential details.


Programming clarifies vagueness. It does this by enabling expression, requiring explicitness, and fostering organization.


Programming's enabling of expression comes from its linguistic nature. To give shape to concepts, first you need a language, and a program is a language for describing a domain, in this case math. In programming you can create bundles of data or instructions in the form of variables, functions, classes, and so on, give the bundles names, and then use the names in other instructions. It's the programming equivalent of creating words and using them in sentences. The range of data and instructions a program can represent is very broad, so you can create whole languages this way. Since they have to be executed, to a certain extent these languages are rigorously defined, and they're called formal languages, as opposed to the natural languages people speak. They also tend to be more like grammars than fully fledged languages. A programming language is the skeleton of a language, and most of the actual words are created when you use it to write a specific program.


The explicitness requirement arises from the logical and passive nature of the computer's execution. Even apart from computer technology, any effective method of executing instructions will be based on logic, since the results would be unpredictable otherwise, and in that case you might as well not even have the instructions. But when humans are the executors, a lot of the instructions can be implicit, since people will fill in the gaps intuitively. This means that if the instructions are written poorly because the author actually hadn't worked out all the details, the person who carries them out can end up with a much better understanding of the procedure than the person who wrote them.

The computer's executing abilities are much more helpless than a human's, and a programmer has to give it an explicit instruction for every single step of its procedures. Not every programmer needs to write all of these instructions, because a set of instructions can be saved in a library or module to be included in later programs, and these libraries are often shared among programmers. But within the realm of procedures that aren't already contained in a library, if the program is to fulfill its functions, then the programmer has to work out all the details themselves, which means they'll end up with an extensive understanding of the program's domain, and many holes in their initial understanding will be filled in. While creating an algorithm, you'll discover a lot of details you weren't expecting, such as pieces of data or whole side algorithms you didn't know you'd need. This will happen even when translating a perfectly adequate procedure written for humans into code for a computer. But to me digging up new information hidden in the source material is half the fun.


Organization groups items that are related and presents them in an order that helps the reader see their relationships. It's certainly possible and even common to write very disorganized "spaghetti code," but if you're following the principle of efficiency, you'll engage in development practices that will organize your code in ways that let it function as a conceptual map. You'll move code around to more appropriate locations, streamline inefficient or duplicate code, or rework whole algorithms, and concepts and patterns will emerge as you do. If you're using an object-oriented paradigm, for example, your data structures and algorithms will get grouped into objects with properties and behaviors, and these objects will relate to each other by using each other in their behaviors or as values for their properties. You may form layers of related functionality, such as in the model-view-controller pattern, where distinct sets of code handle the program's data, its user interface, and the interaction between the two. As you organize, your mental picture of the domain will improve. You'll also think specifically about readability factors such as using consistent naming conventions and using a consistent visual formatting style for your code, which will make the code easier to review.


Programming enforces logic. Instructions written for humans can contain not only gaps but logical inconsistencies. These can be annoying for the people carrying out the instructions, but they aren't necessarily show stoppers, because people can actively determine what the correct instructions are likely to be. A computer, with its passive execution, will simply follow the exact instructions you specified, and if they have logical problems, it'll give you an incorrect result or stop executing the program altogether, leaving you to figure out what went wrong. And as you figure it out, your understanding of the domain will sharpen.

Programming's dependence on logic makes it a good choice for modeling math, since math is also tightly tied to logic. (In fact, looking at the breadth of topics mathematicians consider fair game, ranging from numbers to the grammar of natural languages, I wonder if math could be defined as the study of logical structures.) The translation from math to code can be relatively simple and direct. In fact, math is one of the primary uses for programming, and I think it's safe to say any kind of math people have wanted to do has already been represented on a computer by some programming language.


In addition to sharpening thought, programming gives you the freedom to move through the domain's content in any order, which enables various patterns of coverage. Even code that does very little is still a valid, working program. Additional functionality can attach to a lot of different places in the code, which means there's a lot of freedom in the order of features you add, and in the case of my project this freedom means I can start my code simple, start anywhere in the curriculum, and choose when I address its topics and in how much detail. It gives me the power to follow the needs of my mind and my schedule while reaping the other benefits of programming.

Two examples of coverage patterns are working backward and working breadth first. Working backward would mean starting with the math I need to know for a project and learning about the earlier math that would make sense of it and so on until I got to math I already know. Working breadth first would mean learning all the topics I want to cover at a superficial, procedural level and then passing through them a few more times, learning them at increasing levels of depth. I very well might follow these patterns. Just because I want to end up with a map and because the map-like Common Core material takes a depth-first, bottom-up approach doesn't mean I have to follow that outline, even though it's what I've had in mind till now.


In addition to sharpening thought, programming also gives me a strong subjective sense of security, which is important for my ability to progress in a project. This security is different from the typical IT concerns about data theft or loss from things like hackers or hardware failures. It's the emotional assurance that writing my code isn't a waste of time.

Generally speaking, if I write a program that's designed well and works correctly, the following things will be true: First, the code will be stored, so I won't lose it by forgetting (data loss by wetware failure!). This seems trivial, because it's true of every program or any other content that's saved to a file, but the semi-permanence of stored information is always a subtle but profound relief to me. It lets me stop worrying about the information and turning it over and over fruitlessly in my mind. That obsessiveness comes from the fear of losing ideas I feel are important.

Second, since the programming will have performed its thought crystallizing functions and the resulting code will be reviewable, I'll feel that rewriting my sources' content in code form was worthwhile. And I don't have to wait till the end to feel the security from this factor. Since I have a decent idea of the concerns that result in good code, I have a clearer way to decide whether I'm wasting my time writing each line. But even the simple fact that each part of the code contributes to its functionality is inherently reassuring to me. Each part is worthwhile just because it has a purpose within the program, even if that purpose has little to do with learning. By contrast, I wasn't clear on how well a lot of my prose notes supported my learning goals or any goals at all, which sapped my motivation to write them.

Third, because it's executable in a logical fashion and gives me rapid feedback I can use to verify it, my code will make sense because it works the way I expect. The only way I could independently verify my prose notes would be to have a math expert check them, which is slower, harder to repeat, and still more error prone than a computer.

Fourth, as I described in the previous section, even when the code is incomplete, it's still worthwhile, because it has a solid potential to grow into code that does more.

Project benefits

In addition to programming's general benefits for learning, I can use this particular programming project to advance other projects of mine, both during and after my work on this one.


Coding a math implementation gives me an earlier chance to practice and explore certain areas that'll be useful to me in future projects. I like to kill multiple birds with one (cumbersome) stone. I'd get around to learning at least some of these anyway, but it'd happen much later if I excluded programming from all the time I'd be spending on math relearning. Since they have such broad applications for me, these explorations are as much the point of the project as learning math.

First, I can learn some general programming tools and techniques I've had in mind for a while: mainly Git and GitHub, literate programming, test-driven development, design by contract, and aspect-oriented programming. It might slow me down too much to use them all for this project, but learning at least some of them should greatly benefit future projects, or at least give me an idea of if and when they're worth using.

Second, I can use the project to explore the subject of knowledge representation, which is an aspect of artificial intelligence, which feeds into cognitive science. This project is basically an exercise in knowledge representation, so it's no stretch to study it in the process of writing the program. For a long time I've had the idea that content should be stated in what I call usable form, which means organizing it so I can quickly find the information that's relevant to my needs, such as arranging it in if-then tables or flowcharts. Full-blown knowledge representation would take usable form a step further and make the content executable.

Finally, it'll let me explore the general concept of learning by programming, which is an idea I've had for years but never tried. This introductory essay is also part of this larger project. Since I haven't seen others discussing this approach to learning, for me the idea is an untested but very strong hunch. As I experiment, I'll observe what works and what doesn't, with the aim of developing general methods that will work across disciplines.


At the end, the project will give me code and documentation I can use for purposes other than its main one of giving me a typical American math education.

First, the code can act as a skeleton for organizing math reflections that aren't easily translated into code, such as discussions on math education or the philosophy of math. Some of this will probably happen even as I write the documentation for the simulator itself, though I'll try not to let it distract me for long periods.

Second, it can act as a library for use in programmatic math explorations that don't fit within the curriculum, rabbit trails off the main learning path. There are already math libraries that a programmer can use to run calculations, and they're programmed much better than this one will be, but maybe mine will be organized more conveniently for some purposes.

Third, this project can act as a framework for learning projects in other subject areas. I'm picturing a multi-level framework containing a software framework, an information design framework, a learning process framework, and maybe others. A general notetaking app based on these models is a tempting future project.


With a description of programming's characteristics and benefits under our belts, it's worthwhile to look at some objections someone might make to the notion of backing up in my math relearning project to take this new approach. Given my goal of learning a lot of math deeply and quickly, is it really a good idea?

Won't you spend all your time programming and not get to other important learning activities? That's certainly a danger. I agree with Barbara Oakley that fluency is a necessary part of math learning that can easily be crowded out by a preoccupation with conceptual understanding. Similarly, telling the computer how to do math is different from developing the skills to do it myself. I'm hoping that being aware of the problem will keep me motivated to work on my fluency.

Won't the program leave out a lot of the information you're looking for--a lot of work for not enough result? It's true that it won't tell me everything I'd like to know, but since I want to know how to actually do math and not just what it means, it'll tell me at least half of what I want to know, and it'll give me a better starting point than prose notes for further learning and reflection. And with programming's focus on functionality, it might help me put aside questions I'd like to explore that aren't as important and would only slow me down. Enough conceptual understanding is good. Too much is a distraction.

Won't the overhead of programming take too much time (design, infrastructure, debugging)? Maybe, but certain factors reduce the usual time sink: (1) The math I'll be programming is well defined, so I'll have less to figure out than in some other domains. (2) I'm trying not to be clever. (3) The interface will be simple. (4) Since the code isn't meant to be used, I can skimp on some of the plumbing if it's slowing me down too much. (5) Always remember the Programmers' Credo: "we do these things not because they are easy, but because we thought they were going to be easy."

Wouldn't another learning method take less time? Possibly, but programming can often accomplish the same results better, so I think it's worth the extra investment. Let's look at some other approaches I might take:

  • Teaching. Explaining things to a student does make them clearer and more memorable to the teacher. But this is essentially what I'm doing when I program. I'm teaching the computer. And in some ways the computer asks better questions than a human student because it needs every logical detail fed to it or else it gives the wrong result or crashes the program.
  • Problem solving. Problem solving is an excellent learning method, but on its own it wouldn't give me a map or even easily reviewable notes. Programming has problem solving covered anyway, because that's 90% of a programmer's work. Much of the time it's problems related to the content, and the problems reveal a lack of clarity in my understanding that gradually resolves as I figure out how the computer should carry out its task. But my program won't give me real-world situations to apply math to, so I'll need to supplement my learning with more typical word problems from regular learning materials.
  • Diagrams. I would love to be able to represent math knowledge as a series of incremental diagrams that can be understood and reviewed with extreme ease. I hope I can do that someday. But I'd have to find or invent a visual language that could express everything adequately, whereas I'm familiar with programming already. Plus not many diagrams are executable, so they wouldn't carry the advantages of executability. Programs in visual programming languages are executable diagrams, but I don't know those languages, and I suspect they're not the kinds of diagrams I have in mind. Making more diagram types executable is on my future project list.
  • Pseudocode. It's true that if I wrote my program in pseudocode instead of real code, I could approach the explicitness of regular programming without needing so much of the overhead. But it also wouldn't give me the enforced clarity of actual execution. I might leave out important details or make errors in logic that I'd never notice. It's too easy to fudge with pseudocode.
  • Traditional classroom methods. Here I'm thinking of (haphazard) notetaking, drills, and prepared exercises, focusing on procedural knowledge and troubleshooting that with occasional conceptual understanding. Well, I'm in favor of drills and exercises. But the main point of this project is that programming tells me how to take notes. Taking notes helps you understand what you're learning and record it in reviewable form. I strongly suspect programming will give me a focused, disciplined way to do that, and the thought of going back to random notetaking fills me with mild despair. Programming versus prose notetaking is like the difference between driving on paved roads and off-roading. Both might get me to my destination, but I prefer roads.

Shouldn't you just trust the process instead of trying some new, untested method that'll take extra work? If I knew the process was trustworthy, yes. If someone with the relevant experience could tell me that anyone with my goals, my time frame, and my type of mind will succeed with these traditional methods, then I might get myself to submit to them. But a lot of the problems I've described are really frustrations I had my whole school career across a variety of subjects, and even though I did well in school, I never really got a handle on the traditional study methods. I'd like to try something new. If I can't get it to work, then I'll know it's a dead end and have a good idea of the reasons, and that'll be valuable information.

Do you really need to trace all these conceptual threads so completely? Probably not, but I can start simple and add more detail later until I'm satisfied. I suspect I'll feel able to move on with my studies before I've learned all the details that interest me, and maybe I'll be able to add the rest as a side project afterward.

Doesn't starting over waste time? I have a few points to make on this one.

  • It doesn't feel like a waste. I want a complete map, and starting it from where I left off would give me a big gap or smudge at the lower levels. It'd be like telling a driver they have to off-road for the first part of their journey because the builders couldn't be bothered to pave that area. Sometimes I like to step back and look at the big picture, tracing through the whole outline of a subject to reassure myself that it all works and I know my way around. Gaps in my notes (the program) would make that harder.
  • The cost to starting over is low. I hadn't gotten very far, just taken a long time to do it. This time I'm not covering all that ground--no pre-K and no philosophizing about the fundamentals of math or the meaning of numbers. I'm not even trying to digest all the educational material. I'll be focusing on the algorithms and whatever concepts they require, so the program will cover less territory per grade.
  • All learning involves iteration, and it's better when the iterations place the content in different contexts. The program will cover some of the same ground but very differently from my first reading, which will help whatever learning I still need to do in that area.

This whole project is an experiment to see if the idea of learning by programming can work. Will I learn math as a result? Will I finish the project? Will I even get past arithmetic? I don't know. But when the other options seem worse, not knowing how well something will work is no reason not to try it. And if a project is an experiment, any failure is a success because it gives you valuable information. If the project does work, it's an approach I and others can apply to many other subject areas.