Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Learnable Programming (2012) (worrydream.com)
166 points by noyesno on Dec 9, 2020 | hide | past | favorite | 48 comments


I teach CS to freshmen. The author keeps telling something is "a wrong question", but I feel that he is tackling a wrong problem. The problems shown here are rather syntactic/superficial - it's mostly a matter of language/tool proficiency. The real problem I commonly see among students is to systematically verbalize a thought that you're initially unaware of - e.g. take the binary search for example. The idea can be easily understood, but realizing that a range can be expressed with two numbers (high & low) is hard. Another example is to enumerate all permutations of given items. It's easy to imagine what are the expected result for a certain input, but it's not easy to describe the systematic process - it'd require some mental leap. These are what many people are struggling with, and something we still don't know how to teach.


This comment completely misses the point. The article's title is "Learnable Programming: Designing a programming system for understanding programs"

This is not an article about how to teach or learn programming, this is about creating an environment inside of which learning is made easier.

Try giving a freshman a binary search program with an interactive visualization like the ones shown in this article that they can play with, and see if they still struggle with it. Same goes for the permutations. You don't have to teach anything when you can let someone experiment and teach themselves how something works. At the end of the day, true learning always hinges on personal insight, and the best teaching methods are those that make it easiest for a person to extract insight.


> This is not an article about how to teach or learn programming, this is about creating an environment inside of which learning is made easier.

Looks kinda the opposite to me. It's criticizing a particular learning environment because it doesn't actually help with learning programming.

Right in the middle of the opening section:

> Thus, the goals of a programming system should be:

> * to support and encourage powerful ways of thinking

> * to enable programmers to see and understand the execution of their programs

> A live-coding Processing environment addresses neither of these goals.


This is so spot on. I teach CS as well and just taking a problem and dividing it into small tasks to be solved is something many students struggle with even near the end of our programme. This "mental leap" (the bridge between the problem and the steps to solve it using code) is the real barrier in my opinion. Most students won't have a problem understanding a solution when presented with it and wrongly thinks that just understanding a solution is the end goal, when arriving at it is the real challenge.


That's interesting breaking a problem down into steps seems such an intuitive approach.

Coming from a technical programming background Middle Out is the methodology I often use BTW

Which level are you teaching at? I would expect University students to be capable of "taking a problem and dividing it into small tasks "


I agree. To me, it's the only approach, but I've been doing it for so long. On some level, the students understand this as well, but doing it is a different matter, especially when it comes to programming. I teach on some very practice-orientated higher education programmes in Denmark at the level of a bachelor's degree. We tend to get different types of students than those who would apply for a bachelor's degree at one of our universities, which could also be part of the explanation.


You have a point, but learning to program is hard because it requires mastery of several domains: abstract thinking, mathematical concepts, programming idioms and syntax, debugging and problem analysis, problem decomposition, etc.

I think the author presented a very insightful take on teaching some of the important aspects of programming.


I think programming is actually hard to learn, even at a level where those domains don't really come into play. More than half of the kids in my BASIC class in 1980 never grasped even the most primitive programs. The kids who "got" it, may have been good at the things you mention, in terms of potential, even if they had never actually done any of them by the time they were in high school.

And I think there are good programmers who are lacking in those domains, notably math beyond the intro level, where problem solving involves recognizing the "form" of a problem, and remembering the algorithm for solving it. The guides I've read on making programs more understandable recommend eliminating abstraction, for instance by making sure that the names of things are concrete and self explanatory.

So I actually think it's still a puzzle why programming is hard, or easy. The paradox is that programming is super easy, but only for a randomly selected group of people, otherwise it's prohibitive.

Then again, if you can think of a subject, like programming, where we've tried a new way to teach it in every generation, with no sign of widespread success, it's math.


It's kinda funny how many on HN talk about basic programming being hard, but also bemoan the existence of complex excel-macro-based workflows created entirely by non-programmers.


Learning to program is not necessarily the same as learning to code. If we always think of the two as the same, we'll face the same issues indefinitely.


By "code" mean a syntax/semantics and by "program" architecture/algorithms?


Sorta. Code is the medium of encoding a program, but it's just text. One important part about programming is it gives us a new mode to think in terms of. Another is that it gives us power over an entity (the computer) to execute things. The cool thing about Papert's LOGO was that children already knew how to think in terms of left, right, forward, etc. so they could act out their programs in real life before writing them down. This is one step forward, but not enough.

We have to stop looking at computers as machines with mice and keyboards and small screens that we conquer with code and start thinking of them as abstract entities that execute things, and then think of how best to manipulate those entities to do what we want.

"The computer is an instrument whose music is ideas" (Alan Kay) - Can you imagine what music would look like today if all we could do was write it down and hit play? Where's the emotion and playfulness in that?


I love this kind of stuff, but it feels like shooting fish in a barrel when the examples used are inherently visual. Lots of programming deals with abstract "things" that don't naturally lend themselves to being visualised, and it's there that some of the the more difficult challenges of programming exist (perhaps because they're difficult to visualise in the first place).

I'd like to see Bret's brilliance tackle visualising those types of examples.

Maybe most of it simply can't be visualised, but I feel like there's a lot of unrealised potential in that space.


> Maybe most of it simply can’t be visualized

I feel like having programmed consistently since I was 9 (24years now, wow) this is my biggest strength. When it comes to code and architecture I sortof just see it in my mind. It’s very plastic. Like a malleable thing that my brain does without really knowing how or why. It’s just there.

Can’t even put it into words. Can’t draw it either. Like when you ask math people how they do some of the really complex stuff


This comment resonated a lot with me. Here's something I was thinking about recently:

1) I also started programming very young, maybe eight or nine years old.

2) My first language was Python and I still program in Python today, the programming language with the motto "there's only one way to do it". At some point I had to write Perl for a summer job and it's TMTOWTDI attitude and many symbols nearly broke my brain, I hated it for most of the summer.

3) I used vim and then emacs for a very long time, and recently started using Visual Studio Code and Pycharm. This made me realize that one of my favorite features of any editor was actually the minimap VSC provides on the side by the scrollbar (which Pycharm does not by default provide). Not having it, having it, and then not having it again made me realize I utilized it a surprising amount even though it's a seemingly trivial feature compared to, say, code completion or syntax highlighting. It was just very fast for me to jump around a large file by clicking on the minimap; I knew where to click to jump to the function or class I wanted.

4) I am a vicious style guide zealot. I got poo-poo'ed once by a coworker for submitting a large commit where the only changes were renaming things to snake_case. But the code just looked wrong to me, I had to do it. I write C/C++ in K&R style and find it difficult to read code not indented as such.

I was sitting on my lunch break and all these things kind of crashed together into a great epiphany - maybe the reason I program in this specific way is because the code has to look a certain way in my head. Like I'm literally imagining a sort of minimap in my brain and if the syntax, conventions, order, spacing, etc. are wrong it screws up my very visual model because it literally looks wrong. The more rigidly the code follows the rules, the more visually consistent it is and the easier it is to structure.

Your comment makes me wonder if there really is some semi-visual, semi-textual model that certain programmers form of their code, which is ever-present but really hard to express in other ways. I also wonder if this is a common thing, and if it helps or hurts when programming.


I'm like you - except I started with C++ (and prior exposure to Basic, Pascal, and VBA). The code has to "look right"; it's a visual thing, but there's no describable or drawable "shape" I could point to.

I've been through the "code case and bracket style must match" period, but eventually my brain abstracted over it, and it's now a free variable - I can work with any style, but it must be consistently used, or else it'll trigger that visual feeling of literal ugliness.

I also had a visual enlightenment with Lisp code, where one moment, I thought it was clumsy, and then something clicked, and ever since I consider a (properly formatted) Lisp code beautiful.


I understand this phenomenon all too well. I experienced another, similar phenomenon, albeit not with the code itself.

I've done literally all my best work for the past 25 years in Emacs. Recently I decided to switch to Visual Studio Code because "that's where the momentum is now". Well, it lasted a few weeks and then it was back to Emacs. I wondered why this was.

I realized that despite using Borland and Microsoft IDEs in the 90s, I never acclimated to the way IDEs in general handle small tasks like bracket matching and indentation. Emacs does these things right in a way that virtually every other IDE-like editor does wrong. I can work with vim, but working with VSCode has a sort of tactile (instead of visual) "ugliness" about it that increases friction and makes me actually less productive.

That and the wrong way VSCode handles File / Open by default made me frustrated enough to go back to Emacs.


> Emacs does these things right in a way that virtually every other IDE-like editor does wrong.

?

> the wrong way VSCode handles File / Open by default

?


Right: Electric indent. Tab at beginning of line automatically indents line to desired depth. Editor's guess at indentation level is almost never wrong, and the exact level is configurable.

Wrong: Hit return and the next line is automatically indented; other than that you're on your own.

Right: Flash the opening bracket or quote when you type the closing bracket or quote.

Wrong: "Helpfully" close opening brackets or quotes, but do not provide Paredit-like structured editing features, leaving the user to accidentally type spurious extra brackets/quotes. (Some IDEs skip over the preinserted closing mark when you type the same mark with point on the closing mark. But they're woefully inconsistent about this and Visual Studio Code does not do this.)

Right: Visiting a file does not otherwise affect editor state.

Wrong: All state for the editing session in the current window is clobbered when you do File / Open from the menu. User must spawn a new window in order to preserve editing state in this window.


Quietly pleased to find I agree with your wrongs, especially “helpfully” adding a closing pair item, but sad I haven’t used something that does them better.


I can relate.

Speaking only for myself, I’m a wee bit “on the spectrum,” and basically work in some kind of “symbolic IDL,” inside my head.

As long as I never need to verbalize my design, I can keep a pretty massive architecture completely unwritten, in my mind. This makes it possible to work extremely quickly, with big “on the fly” changes to my implementations; performed “inline,” as I work.

The moment that I need to verbalize or “overall” document things, though, the whole gravy train comes to a screeching halt, as my brain needs to do some kind of “context switch.”

BTW: my code is pretty “anal.” Highly formatted and documented. I actually feel physically uncomfortable, if it isn’t formatted the way I like.


I love the way you've put this.


Yeah, I’ve always found this sort of Bret Victor argument weird: yes, perhaps more graphical tools are the future. However—in both writing and math, it seems like there’s a tendency to start with more pictographic notations (Egyptian hieroglyphs or Greek geometrical figures) and move towards more abstract notations (phonetic alphabets or algebraic notation). It’s not clear to me that attempting to reverse the trend and pictorializing programming languages actually benefits anyone, except when learning. it’s a bit like my experience learning Lisp: when I started out, I was really into indentation-based syntaxes that hide parentheses; once I started to internalize the structural editing tools, I discovered that the “cluttered” parenthetical notation was actually a reason _to_ use lisp and not something to be covered up.


You make a great point about notations becoming more abstract for more advanced use cases, indeed this may be a "natural" process. However I'd like to add nuance with the observation that Bret may not be suggesting that we reverse the trend from abstract notation back to concrete visualizations. Actually I think he is calling for a rich variety of visual/concrete notations and symbolic/abstract notations that work in concert together to express our dynamic concepts, and extending those with the use of the dynamism of the computing medium to add interactive aspects to the notations (ala "Magic Ink").

His talk "Media for thinking the unthinkable" goes into detail on this, especially from minute 10 to minute 17: https://youtu.be/oUaOucZRlmE?t=600

The essay Magic Ink: INFORMATION SOFTWARE AND THE GRAPHICAL INTERFACE also goes into detail about this topic http://worrydream.com/MagicInk/


Yup, when I do programming, I imagine the data inputs to be some "shape" and, in my mind, that shape transforms as I apply operations to it, like `filter`, `map`, `take N`, etc. I just visualize what I want the data to do, then start modifying it.

Another set of analogies I use is that the data, to me, is like clay or a block of wood, and I'm either forming or carving it depending on the context. For example, if I am doing some calculation where I take several bits of data and combine them to get a result then I'll imagine "forming" the data like clay in my mind as I apply mathematical operations to it like `*` or `sin`. If I'm doing stream operations in some "rules engine" where I need to sort through the data, rather than a straightforward equation like the former example, then I imagine "carving" the data like wood with `filter` or `reduce`.

I also get a "feeling" when I look at code or architecture as to better ways to do it, I don't have evidence at the time to support my feeling, but later on they are often correct.

Also, I don't break things down into tasks as such, but I do start a project/task by commenting with TODO at high level and then drill down, much like a functional programmer would do so. For example, if I'm writing a tool to count the number of lines in a file, I would start with something like:

    # TODO: initialize the program

    # TODO: load the file

    # TODO: count the lines

    # TODO: output the count

    # TODO: finalize the program
Then, as I go along, I add the more-specific steps to replace the "load the file" (or I just remove the TODO prefix and it acts as a organizational sectioning comment), and eventually I'll start taking those comments and turning them into code/functions when they're sufficiently atomic. I kind of imagine this as a combination of clay and wood, I'm building up the comments like clay, but also sort of "carving" the raw comments into code (the block of wood is an empty file, and I'm carving it bit by bit into the form it will eventually become: a file that compiles into a program that does what it should).


Yep, I definitely do something similar. I respect Bret Victor greatly (his Magic Ink essay has had more of an effect on what I do as a career than almost any other single thing), but I've never really been completely on board with this idea -- though in fairness it's a response to an implementation of a very specific programming environment, it's not a general solution.

Re mentally visualising, I'm reading a book called Mathematician's Delight[1] at the minute, and its first chapter has one of the neatest pieces of writing on abstract reasoning that I think I've ever read, it's reified a lot of instinctual ideas I had about how I program. I've clipped quite a lot of notes from it -- this in particular is relevant I think:

"Beginners in geometry are sometimes puzzled by being told that straight lines have no thickness. We shall never, we are told, meet a straight line in real life, because every real object has a certain thickness. One of Euclid's lines, however, has no thickness. Two lines meet in a point, and a point has no size at all, only position. We shall never meet a point in real life, either, for all real objects have a certain size, as well as a certain position It is not surprising that pupils wonder how we know anything about objects which no one has ever seen or ever can see.

This difficulty is a good example of the confusion which can come from misunderstanding the methods of abstract thought. We have seen that Euclid's geometry grew out of the methods used for building, surveying and other work in ancient Egypt, This work was done with actual ropes or strings, real linen threads with actual thickness. What does Euclid mean when he says that a line has no thickness, although he is using results suggested by the use of thick ropes? He means that in laying out a football field or in building a house you are not interested in the size or the shape of the knots made where one rope is joined to another. If you allowed for the fact that ropes possess a definite thickness, if you carefully described all the knots used by a bricklayer, you would make the subject extremely complicated, and no advantage would be gained. Euclid therefore says, if an actual rope has thickness, neglect this in order to keep the subject reasonably simple.

The position is not that Euclid's straight lines represent a perfect ideal which ropes and strings strive in vain to copy. It is the other way round. Euclid's straight lines simplified account of the complicated way in which actual ropes present a rough, behave."

[1] https://archive.org/details/mathematicians-delight-w.-w.-saw...


In context, he was responding to Khan Academy using these same examples in a learning environment that they said was inspired by Bret Victor.[1] For what it's worth, he has been working on a collaborative computing space called Dynamicland for some time now that does explore his ideas and fit in with with his ideals.[2]

[1] https://www.khanacademy.org/computer-programming/drawing-bon...

[2] https://dynamicland.org/


Maybe it can't be visualized (but I doubt it-I'm sure it can), but I don't think it must be. The goal of Brett's arguments is how to teach students to learn programming, not making every programming problem ever visual.

Once a person learns how to think about programming problems, they become better at creating their own mental models and visualizations. And maybe someday they'll figure out how to create visualizations of these complex things you and I can't yet :)


"People understand what they can see. If a programmer cannot see what a program is doing, she can't understand it."

I think about this all the time. In my area I see a lot of programmers who don't do a great job at writing optimal code but it's not because they are lazy or stupid but because they cannot understand something they cannot see. This is why some kind of appropriate visual idiom for efficient core usage and time spent is a necessity in any project that cares about efficiency. I still don't think we have found the best visual idiom but we have to keep trying to make obvious visually, the way a computer really works.


I don't think there is a "best" way of doing it, it depends a lot of what the program is doing. Sometimes it's a tree, a graph, a list, rich text and so on. I think it would really be helpful if it was dead simple, to setup a visualization of a class or a group of classes, directly in code (as part of the PL) and have them update in real time. Right now it's "execute, dump graphviz code, drop it into graphiz". Then hopefully every class has a visualization just like every class (should) have Tests. Right now almost all of my classes have a "string Debug() const", method, to see it's content.


Well - the quote is not true. People who are blind can also understand things. Visual is only one way of understanding.


For context, Khan Academy used some of Bret Victor's writings as inspiration for their teachable programming courses back in 2012. A lot of their work was well-intended but missed the point of his essays, and this is Bret's response. Not sure if Khan Academy improved their course afterwards.


I want this IDE. I want to be able to write a loop and see a timeline of all the steps, arranged like these video concepts. Certainly for teaching children—the 11-year-olds I taught at Girls Who Code pre-COVID would absolutely benefit from something like this—and possibly even for my own use when debugging certain types of problems, depending on the editor's robustness.

This article was written eight years ago, and every year since, it has been dutifully posted to Hacker News, where we all stare in wonder at the concept... and yet nothing like this exists yet?

"Why has no one else done a ton of work (that I'm also not planning to do)?" is never a great question, so I don't want to be too flippant... but seriously, it would be an excellent project, either for someone stuck at home in lock down, or possibly even as the basis for some sort of coding education startup.


imho we are still riding the peak of inflated expectations when it comes to Bret Victor stuff.

I'd rather see focus in making our current batch of tools way better rather than looking for direct manipulation methods, A.I. assisted no-code environments, novel user interfaces, retro-futuristic hypercard-excel mashups, etc etc</grinch> :-p

To be fair "seeing" doesn't necessarily mean drawing vector graphics, any advance helping reveal hidden structure of a codebase or generate better documentation would also allow us to better "see" the working of the code... I'm all for that!

I hope things like model driven development get a second renaissance at some point, without the burden of UML, the sad XML reputation, "extreme programming" BS and such.

One project I like that's futuristic, and yet has reasonable goals, is Unison [1].

1: https://www.unisonweb.org/


> To be fair "seeing" doesn't necessarily mean drawing vector graphics, any advance helping reveal hidden structure of a codebase or generate better documentation would also allow us to better "see" the working of the code... I'm all for that!

This is basically what a good debugging environment is. Some of the best tooling out there is the dev-tools of modern browsers: you get a regular debugger where you can step through code and see the state, you also get some performance and memory visualization tools, you get an interactive html editor in which changes are reflected in real time, you get color pickers when modifying css colors, you can visualize the timing of requests, and you get autocomplete propositions all over the place.


100% agree, debuggers are often neglected. Chrome's debugger is one of the exceptions. Java has great debuggers too.

Debuggers are about the dynamics of the program... I'm thinking more about the static structure of the codebase. Tools like sourcegraph [1] address some of that. The STEPS report [2] comes to mind for other cool ideas in this direction: it is easier to navigate the code if there's less of it!

1: https://about.sourcegraph.com/

2: http://www.vpri.org/pdf/tr2012001_steps.pdf


I've read this post time and time again. But I'd like to mention, for me learnable programming is and has been firing up a debugger. I'm learning 3 things because of it:

1. See how state changes

2. See what hidden state there is

3. See how state changes if I interact with it. E.g. in C by changing register values or variables. In Python by changing variables.


I would also like to mention that university TAs/teachers didn't teach me how to use one (never). I just ran into a CS student that already happened to be an experienced programmer, and he showed me.


If you liked this article, you should not ignore Bret Victor's recommendation to read Seymour Papert's "Mindstorms" [1]. Whilst "Learnable Programming" is a critique of programming education approaches, Papert's book can be seen as a critique of the education system. It was truly ahead of this time. This book describes ideas behind Logo/Turtle and its use for teaching programming, but it goes beyond just that - it's more about teaching everything through programming, including maths and geometry.

Shameless plug: I'm also trying to implement these ideas at Low-Level Academy [2], teaching systems programming concepts in a visual way.

[1] http://worrydream.com/refs/Papert%20-%20Mindstorms%201st%20e...

[2] https://lowlvl.org/



Does it work though?

Suppose I want to minimize the time taken from someone having not done any programming, to implementing a B+ tree. Is this really what you would recommend?

Also, sometimes code takes a long enough time to run that one can't instantly show the results upon changing some code. That's not something you can dismiss with "that's just asking the wrong question". There are actually things that need computing, and some of them can't be done quickly.

I wonder if a good measure of a programming curriculum might be, how quickly can a student become able to make something self-hosting (though, the curriculum should have various natural stopping points before this point, depending on what skills they personally need).


> Also, sometimes code takes a long enough time to run that one can't instantly show the results upon changing some code.

That’s true, but it’s not a good argument for not giving instant feedback when it is possible.


I've only read the first few sections and am already agreeing fully. In fact, I don't think he goes far enough:

> Likewise, guessing the third argument of the "ellipse" function isn't "learning programming". It's simply a barrier to learning.

It's even worse than that. The "ellipse" function should only take 2 arguments - a point and a size (or 2 points if that's your thing).

I see so much of this sort of terrible API design, especially in graphics where good API design makes things so much clearer and easier to use. Writing out a point and a size as 4 variables is madness.


> The "ellipse" function should only take 2 arguments - a point and a size (or 2 points if that's your thing).

How do you handle ellipses with different eccentricities?

There are several equivalent representations of ellipses, one of which is the two foci and the sum of the distances from the edge to the two foci... so two points and a distance (or you could use two points and the major axis, etc., etc.) A pair of points don't uniquely define one ellipse. Likewise, a center and a "size" doesn't uniquely define an ellipse.


I think maybe they meant for an ellipse drawing function which, like the one depicted in the webpage, only allows ellipses with both axis either horizontal or vertical, and was suggesting that the "size" argument would have 2 numbers to it.


Yes, that's what I meant. Obviously there are other ways to represent other types of ellipses, but given the constraints of the example in the article, I thought that was clear.


> A pair of points don't uniquely define one ellipse.

What if the two points were the corners of an enclosing rectangle? This is how, for example, Gimp does the ellipse selector tool.


There are multiple ellipses bounded by that rectangle, unless you limit yourself to ellipses with major axis either vertical or horizontal.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: