Programming as a Way of Thinking
blogs.scientificamerican.com
blogs.scientificamerican.com
This is exactly how I understood it. Three years back, WebAudio API was a new addition in browsers and I decided I should make something with it. I settled on building a Whistle Detector using a cited research paper as my basis. I barely understood anything in that paper and had to dig into DSP, FFT and other basics to get around. As I had no external help, I struggled plenty but managed to complete it after two weeks [1].
Funny enough, we had a DSP course which never made sense to me. Two weeks into my puzzle I walked away with more useful knowledge than the course ever did. What has always motivated me to learn is the application. I can work tirelessly if there is an interesting thing to build, even if I have to go through mundane theory. But, I find it utterly tedious to learn theory with no immediate goal in mind.
It seems some people love theory/understanding while some love building something practical/useful.
If I were you I would send an email right away. You never know what happens.
http://blog.wolfram.com/2010/11/23/conrad-wolframs-ted-talk-...
It's sad to see educators like this get pushed out of their field. I had some incredible teachers as well, but also some awful ones. There needs to be greater competitive components added to the education system, such as statistically significant pupil success in education and career outcomes.
There is a popular objection that "not everyone should be able to code". But it depends on the "to code" definition. A good example here is with game designers. They may not know how to do low-level coding, work with 3d math or use C++ templates. But still for a really good game designer it's very important to have algorithmic thinking and they need to have a tool for testing their algorithmic ideas on the computer.
As for Python, there is an issue: it's hard to find examples of good style of Python programming (I think only few of us actually learnt Python with help of textbook). Some time ago I was happy to find notes by Peter Norvig about Python and about comparing Python and Lisp. His code is very elegant, see, for example: http://norvig.com/python-lisp.html
[1] http://www.sciencedirect.com/science/article/pii/01656074819...
I've never really bought that this matters so much as long as you just write sensibly in general. How many python users really make sure to do everything a "pythonic" way?
1. "Executable pseudocode", almost a toy language to explain few algorithms in your article.
2. Sysadmin tool. Replacement for shell, a way to write quick throwaway scripts.
3. "A modern Lisp". Universal language for implementing AI algorithms, DSLs etc.
I, personally, use 3rd variant. I write quite big programs in Python, for example I made few compilers in it. That's why code quality is important for me here.
I have just started reading his Think Stats book http://www.allendowney.com/wp/books/ which is starting to help me better understand statistics. Not far enough into the book yet to make a complete judgement however.
Got to say I like seeing different perspectives on traditional subjects. My youngest is going to Olin next year in Mechanical Engineering and seeing these sorts of articles keeps me excited about her unconventional engineering education at Olin.
Some thing I want to play with more is OS-y scheduling and AI-y thought as ways to think about time management or problem-solving for "humans."
The "Learn how they work later" part sends out alarm bells to me. I don't have a lot of confidence that students will be particularly motivated to dig into how an algorithm works after their problem has been solved I fear this will lead to a generation of "just use $x package" and people blindly plugging in "magic algorithms" without understanding their choice. "Quicksort for everything" or "include leftpad" if you will...
I see it a little in my industry (Engineering) "oh your data is noisy just apply a kalman filter" never mind if it is appropriate or not.
A benefit of the bottom up approach, of starting with the math and no reference implementation, is that you are less likely to implement it unless you understand it. And I should stress, these are tradeoffs.
"This is how programming should be taught. You should do stuff way before you can figure out how it works. For a while, you should intentionally be ignorant about distracting details."
"You should, intentionally and tactically, decide which piece of information you can do without, for now. But you should also, intentionally and strategically, decide when to pay back that debt."
This is the first paragraph. I understand that it's just setting the stage, but it makes so little sense by itself that I had to make an effort to continue reading.
I think he was trying to articulate how much more expressive/extensive programming languages and libraries (and tools?) have gotten over the years, so that a student can get to do something interesting with much less down-and-dirty arithmetic and arcana.
The actual programming method haven't changed much since the dawn of Unix, or perhaps Lisp - although it took a while to spread.
The article misses what I believe is the most important point, which is the concept of the abstraction of a function. A function is more than a computer concept: a function is a hammer, a violin, and a microscope; you put an input and you get an output.
I would, however, welcome the companion article, "Thinking as a Way of Programming", to balance the prevalent notion that testing is the only way that matters.
[0] https://en.m.wikipedia.org/wiki/Structure_and_Interpretation...
[1] https://en.m.wikipedia.org/wiki/Structure_and_Interpretation...
Seems like a strange claim, because
> eight of the top 10 CS departments, and 27 of the top 39, teach Python in introductory CS0 or CS1 courses. [1]
[1] https://cacm.acm.org/blogs/blog-cacm/176450-python-is-now-th...
(http://allendowney.blogspot.com/2017/04/python-as-way-of-thi...)
PS There is a written version of this, but I could not find a copy that wasn't behind a paywall. Perhaps someone else can.
Languages like Nim are very promising on that front.
Let's put this under the heading, "One Size Does Not Fit All".
The underlying assumption of this opinion is that there is only one model to teach too.
In the modern era we really need to take into account our differences.
In this case, functional versus procedural programming.
1. Write this in a Lisp as functional.
2. Present the functional form as human readable as the given procedural.
3. Conduct a study and gather the data.
4. Present the findings.
My experience has taught me that there is subset of the human population who think more naturally in functional programming.
But if one model is insufficient? then why would two be?
What languages are yet to be invented to meet the needs of the millions of daily programmers?
It is time for experimental science to be conducted given the millions of people involved.
The path has already been laid out with Usability research that is entirely experimental.
It is time to do the hard science on usability of claims of functional and procedural programming languages.
It is time to put to rest opinion and one size fits all.
In the software business we learned a long time ago to name our variables properly, name our functions logically, and to control complexity by breaking ideas into modules and then hiding the details inside.
If you can't name something, then you don't know what it is, and that tells you that you should rethink your design.
Mathematicians don't do that. They name variables "a" or "x", or worse, they use some Greek letter I can't type on my keyboard. They are entirely inconsistent in their use of variables: "phi" or "theta" can mean a zillion different things. I can't tell you the number of times I've read a computer science paper, a paper that uses entirely unnecessary equations, and doesn't bother to define symbols. This practice wastes everyone's time.
It's laziness, pure and simple.
Mathematics needs a general overhaul. The language of math needs to a complete redesign with a focus on understandability. And the key to it is to force mathematicians to name their variables.
Yes, I realize that mathematics deals in abstractions that have little relationship to the outside world, and it makes little sense to call a variable a "dog" or a "car". So what? It just means that we need a new vocabulary, a vocabulary that includes terms like "fourier transform" or "hypotenuse". Pretty much every industry has it's own vocabulary. Chemistry has thousands of terms. Biology even more. Computer science is full of them. Math is full of symbols that have no inherent or well-understood meaning. That should change.
I've studied enough. High school and several courses in college. Enough that I should be able to take it from here and learn on my own.
I come from the other direction. I studied math first. And yes, at first I had an issue with the long variable/function names. But soon enough I realized that programming is done quite differently than math. With IDEs and autocompletion, long variable names are not really a problem.
One could argue that variable names should be descriptive in programming, because there is a lot more reading involved. Whereas in math, there is a lot more writing/doing involved. I might manipulate a math variable name 1000 times in my head in the process of working on a problem. I might even WRITE it down that many times! In programming, I might READ a variable name 1000 times in debugging.
I find a good paragraph explaining what the equation means and implies is far more useful than the equation alone.
This is all the typical "what" vs "why". If you just want to describe the what then the formula alone might be enough (and just presuming everyone know what the variables mean), but if you actually want to convey a some meaning that formula needs to be explained.
Before your response I had several hours with just downvotes and did not know why. I wish people would comment with their downvotes.
Sometimes a variable does not refer to anything specific at all. For example, type variables in Haskell are often denoted using single letters, simply because they can be literally anything, and no sane human wants to type out 'anything' all the time, just so her code can be used as a beginner's intro to the language in question.
I understand that not all languages are powerful enough to allow defining functions that can operate on any type. But this doesn't mean that languages with this expressive power should refrain from using it; it means that users of less powerful languages need to learn something new (as I had to).
That's why all popular typed languages after C provide a facility for writing parametric code.
And without exception, the standard libraries for those languages using single-variable names (S,T) for types. Because when you have 1-3 type variables, and you're writing generic code, "Type" doesn't really communicate anything that "T" doesn't.
> design for your system
We're not talking about programming; we're talking about math; that's the whole point.
I just think they are different enough that not everything is analogous, including best practices on variable naming.
x: "some real-valued variable"
n: "a countable quantity, usually a total"
i: "an index"
k: "some kind of constant", often an integer, whose value doesn't change, "c" is also used for this
e: almost never used as a variable, it's Euler's number
p: some kind of probability, or a prime number, along with p and q
t: some kind of parameter, often goes from [0,1] or (0,1)
z: complex numbers
I have a Master's in EE so I've studied this a bit.
Of course, this mathematical convention carried over into programming as well, with i,j, and k serving as index variables.
u, v: elements of vector spaces
G, H: groups
g, h: elements of groups or
g, h: homomorphisms, isomorphisms etc
e: group identity
K, F: fields
I: ideals
f: functions
(x): sequences
x_i: i-th element of a sequence
A, B: matrices
It all depends on the context it's used of course
But anyone who is serious about writing maintainable code today should be using an IDE where the benefits of susinctness are entirely relegated by intellisense-like tools.
Trading readability for conciseness is near the top of my list of "crimes against future maintainers."
So I had never thought about this in the context of mathematical symbols, but this makes total sense and I'm strongly in favor of relegating mathematical conciseness in favor of readability and specificity.
Compare the two following statements:
One from Euklid's elements (written 2.5k years ago):
"Given two straight lines constructed from the ends of a straight line and meeting in a point, there cannot be constructed from the ends of the same straight line, and on the same side of it, two other straight lines meeting in another point and equal to the former two respectively, namely each equal to that from the same end."
And my attempt of translating the above, in what should effectively be Hilbert's notation (19th-20th century):
If there are two triangles ABC and ABD where AC=AD and BC=BD and C and D are on the same side of AB then C and D are the same point.
Which one was easier to parse in your mind?
As a bonus try rewriting this formula using longer variable names and tell me how legible it would look http://i.imgur.com/wCWkyNL.png (it's from a proof of one of Syllow's theorems https://en.wikipedia.org/wiki/Sylow_theorems )
Altough, judging by the old timey language of the book, it's possible the book predates Hilbert's axiomatization of Euclidean geometry and the proofs in it were good enough for the standards of its time.
In modern mathematics proof by picture generally means you've drawn / pointed out a single example, possibly wrongly or in a way that doesn't generalize, and because you've shown that one example holds you assume all possible examples hold. That, obviously, needs not be the case.
So, while you might be used to that notation and in context it's clear that's far from universal. Further someone can be an expert in more than one area and incompatible notation slows down collaboration for little gain.
I agree with you there, notation should be defined, otherwise it doesn't help explain anything.
However, consider that for people who are already used to the notation those "unnecessary" equations are actually more compact and precise than reading the accompanying text. What seems difficult to you may be easy for someone else, and vice versa.
> ... the key to it is to force mathematicians to name their variables.
I believe you overestimate how much of an improvement that would be. How much code have you seen that had variables like int num or String str? If num can be any arbitrary number, and str is just a generic string, there isn't necessarily a more descriptive name you can use.
Mathematics is full of these cases. Say, some general equation involves three real numbers and a real valued function of two real parameters. They are completely generic, so a mathematician might name them x, y, z and f and write the equation as f(x,y) = z.
How would you call them? All I can think of would be the first parameter, the second parameter, the result and the function, which is not much more descriptive for the added verbosity.
The problem with using descriptive names in mathematics is that most entities you are dealing with are so generic that naming them doesn't help. Of course I'm not opposed to e.g. writing NormalDistribution instead of just N, since this is actually a very specific concept. But there is just no way to completely eliminate single letter variables from mathematics without using an equally nondescriptive replacement.
https://en.wikipedia.org/wiki/Quadratic_formula
It is impossible to get better than one letter variable names here. This goes for most expressions in maths, to make things simpler we just use one letter variables for everything. This forces us to learn that the names aren't important, all that matters is how the names relate to each other.
The problem with notation only occurs when non mathematicians start to write down formulas without properly defining what everything is. This is not a problem with mathematical notation, this is a problem with statisticians/economists/physicists/Computer scientists etc who define their own global naming rules where P might denote probability/price/momentum/polynomial time problems etc.
X and Y are descriptive of an overwhelmingly common abstraction, the cartesian coordinate system. They do about the best job they can do.
The coefficients (a, b, c) are opaque. It seems like they would be better generalized as (C_2, C_1, C_0) (or subscripts instead of _#), to let C_N represent "The coefficient for the x^N term of the polynomial").
A few extra characters that are acceptable to mathematicians (subscripts are ++good) would make the formula much more readable, and lets us generalize to higher-order polynomials for similar solutions (not that they necessarily exist).
\sum(i = 1, n) a_i * x^i
And other similar conventions.A struggle for me over the years has been that there does not really seem to be any way of learning the notation, separate from the standard university education process. I'm not about to drop out of my career and go back to school just to learn to read mathematical notation, and it's basically impossible to look up the definitions for obscure symbols with unguessable names, so I simply remain ignorant.
https://ericlippert.com/2016/11/30/4498/
As with virtually every other CS paper using math notation, I found the Damas & Milner paper utterly incomprehensible at first, but once I'd seen the formulas translated into a notation I can actually read, I was able to go back and learn something useful from it.
Unfortunately, it appears to be the case that there really is no one such thing as "math notation", not in the sense that there is one programming notation called "Python" and another called "Haskell" and yet another called "C++", such that one can go read a tutorial for some specific language and thereby come to understand how its notation works. Instead, it appears that "math notation" is a huge collection of little micro-notations, all mixed up together in a more or less ad-hoc fashion by the author of each paper.
And you're making a typical programmer mistake in thinking that.
Programming is geared towards having people who are experts in programming, but not in a specific subject area, be able to develop and maintain code. Therefore practices like descriptive variable names help provide context to people who cannot be expected to have a deep understanding of their subject.
By contrast mathematics is geared towards having people who are experts in a particular branch of mathematics be able to think and communicate with other experts.
Experts naturally create jargon. Jargon is that it is short, concise and precise. This frees up the mind to be able to consider more complex statements, and removes mental friction from more complex manipulations of those statements. Over a lifetime of expertise, the mental effort of learning the jargon for your specialty gets repaid over and over again.
Mathematics takes this to an extreme. And for professional mathematicians, it is repaid in spades. There is an obvious barrier for generalists who wish to approach a mathematical topic. But your experience of how to be a generalist does not make a mathematician's experience of how to be an effective specialist any less valid.
(Note, this comment is informed by my experience having done mathematics into graduate school, followed by 20 years as a professional programmer.)
Programming is getting simpler all the time. Compare modern Python or Ruby to the earliest punch cards. We programmers are going out of way to make it as easy to understand as possible for as many as we can. There are programming languages suitable for children to use while making robots out of Legos.
It is hard to see how variable names vs single character variables creates more friction than it reduces and might even allow domain experts outside of math without higher level math degrees in.
I am curious what other practices are history vs objectively pragmatic requirements. There is much greater pressure on programmers to use time efficiently so we spent a lot of time on pragmatic thinking, and we are nowhere near done. By contrast you sound like many mathematicians and niche experts claiming that you have it solved and know the most efficient way to proceed without even considering an experiment.
In fact, in my own research for my Master's degree, I only made breakthroughs once I simplified the notation. And we're talking about a change like Q(x,y,z) -> Q, Q(x,0,y) -> Q_2^0, dQ(0,y,0)/dx -> Q_{1,3}^{1,0}. The power of concise notation can be quite a bit greater than that increase in opaqueness it creates.
The way math is communicated suffers from this, for sure. However, you gotta think about what will happen once you read a paper that has more descriptive variable names. You sit down to prove a few results. You start manipulating concepts and symbols. You end up shortening the names until you basically come up with your own concise notation. The thing is that how math is read is very much linked to how math is done.
As a topic goes from specialists to generalists reusing a tiny set of terms becomes a horrible waste of time. Worse, math becomes less precise when different areas reuse terms like infinity, set, numer, area, etc to mean vastly different things let alone identical notation for different ideas.
You might be surprised by how many mathematicians would disagree with the assertion that "math is useful" (I suspect a majority would at least think such a statement was overly broad).
Worst outcome I recall was being yelled at by a professor for not getting a PHD. ¯\_(ツ)_/¯
Yes, there are are some areas of mathematics that are extremely specific and do require experts but a lot of math is useful to people in general and anything we do to make it easier for a new person to learn is something that will help the average person use it and will also make it easier for new people to enter the field.
If you want to write some articles that make mathematics more accessible to the general public, and you want to use longer variable names in order to do that, nobody is going to stop you. It's unreasonable, however, to expect mathematicians to try to do this at the same time they're doing their actual jobs.
The more that you get to stuff that you juggle around, the more that conciseness matters. So an important concept like "eigenvector" can have a lengthy name, but your vector is v, linear transform is T and the matrix representing the transform is M. Any other choice is actively harmful.
"Translating" the math into Python code[1] helped me understand what these definition were saying and identify algorithms for exam time. The downside is that it took a lot of time and may not have been as effective as grinding practice questions.
1 - https://nbviewer.jupyter.org/github/bryik/jupyter-notebooks/...
When it comes to proofs, you can only keep so much information in your head at once. In most cases, if you have a ton of variables floating around, you are probably trying to do too much at once and would be better served by breaking out a lemma or two from the main proof.
I will note the worst code I've ever read was written by a control theorist that used only single letter variables. I later found out the variable names were the same as a paper, but the paper was not provided in the program comments.
> Pretty much every industry has it's own vocabulary.
So does math. Open up any textbook and you'll see definitions everywhere. When it is useful to name something, mathematicians normally do.
This becomes less of an issue once you go through some abstract algebra. But typically, constants would come from the start of the English alphabet, and vectors, from the end.
> I will note the worst code I've ever read was written by a control theorist that used only single letter variables. I later found out the variable names were the same as a paper, but the paper was not provided in the program comments.
Did the code remain "worst" after you found out the names came from a paper?
That rule gets broke quite a bit though. For example, if you have a optimization program with some affine inequality constraint A * x <= b, it's not uncommon to refer to the individual hyperplane constraints as a_i^T x <= b_i.
Math obviously has many more concepts than we have notation so selecting a unique notation for each concept is not feasible, but I bet some standardization can be done.
> Did the code remain "worst" after you found out the names came from a paper?
No, I am fine with naming things after variables from papers, but I always put a note as to which paper the notation came from. Giving someone a few hundred lines of code where few variables have more than 2 letters and no context is just cruel though.
https://jeremykun.com/2013/02/08/why-there-is-no-hitchhikers...
Importantly, this language and its practices have evolved over centuries, in response to a lot of different competing needs. It's probably highly-optimized for something, just not what you need it for.
That said, if you're dealing with indices of an array in a sum / product series and that array is of complex numbers, it's actually not terribly ambiguous to do x_i * (2i - 1) or something.
On the other (third? gripping?) hand, you do have a point - there's usually unwritten practices about what different variables reference (theta is usually an angle, k is a constant, n an integer, usually). That can be gatekeeping, and it's super-frustrating to work in a language that doesn't expose type information.
You might want to read some very old math books that predated the introduction of symbols to stand for things. Go read how ancient mathematicians express Pythagoras's theorem. We have verbose monstrosities that is much more simplified now.
Natural language is verbose. Once you can deal with the level of abstraction, conciseness reduces your cognitive load significant.
However, there are forces working against that. Mathematical proofs are more like sentences, or even poetry, than a structured language that can be compiled. They are meant for humans to read. So you jot down your proof over and over again in different formats, playing with both the logic and also the visual representation.
Another issue is that a lot of math is done just in your head, so you don't need a computer at all. When writing code you inherently need to test the codes execution, and also more frequently reference digital materials in your research.
In part because it's one of the oldest taught subjects, I think the field has gotten away with how it teaches. In every other field we have an escalation ladder of abstraction that starts from tangible descriptions that a motivated learner could understand all the way up to symbolic jargon that is only accessible to insiders.
Math doesn't have this at all. It goes from arithmetic straight into symbolic manipulation with only a sideways glance at describing three dimensional shapes. It's lazy and the field needs to acknowledge that it has practical dimension as well as a theoretical one and each needs to be taught and described differently.
No: it's assembly language, for the hand and pen.
Descriptive Variable Names: A Code Smell. http://degoes.net/articles/insufficiently-polymorphic