The paper wasn't linked as far as I can tell but is probably https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7738192/pdf/eli...
While the programmers lay in a functional magnetic resonance (fMRI) scanner, the researchers showed them snippets of code and asked them to predict what action the code would produce
I have a suspicion that writing code and understanding that written by someone else are different skill sets.
I feel like this is akin to asking someone to read a fairytale and to tell you how many times a person crossed a bridge in it, or what they carry in their hand in the end, or where the apple is when all is done.
I don’t think this is about understand what is written, it’s about figuring out what that which is written means.
That’s an excellent point.
I’ve realized that I sometimes read code in more of a “story” mode, where I’m just looking for the gist of what’s happening and what it is “about” rather than the nuts and bolts of how it actually works.
“Story” mode is why I like to organize my code top-down, often with definitions appearing after their usages.
It makes the code read more like a story from top to bottom.
Some like to organize their code such that any term always appears before it is used. Like a math proof or something. I find this somewhat pleasing but unhelpful for understanding the “story” you mention.
Both programs and math proofs are allowed to be written in story mode where definitions can come after their usages. Unless you write in C. There's no story mode in C :-)
There is CWEB. Literate programming is the ultimate story mode.
wtf is CWEB? I presume you're referring to something other than "China Internet Index Bull 2X ETF"?
See: http://literateprogramming.com/cweb_download.html
The clue is in the next sentence.
If you look for cweb by itself, you might get weird results, because there are only so many four letter acronyms / words. Look for 'literate programming cweb' or just 'literate programming'.
But there’s a postmortem, in the core file.
Maybe that’s just a photo of the crime scene.
Sure there is, what do you think header files are? Just use a prototype and defer the actual code to a lter point in the file, voila, story mode.
If you forward declare things there are. The compiler really just cares about the shape and the symbol it has to call.
in C there is only epic mode :)
Yes, it drives me nuts that e.g. Python makes you put the definitions before their use!
well, it is like introducing the characters before they play a role
Compare https://en.wikipedia.org/wiki/In_medias_res
Yeah: to me, it really depends on the story being told, and frankly even then it might depend a bit on the proclivities and interests of the person reading the story.
The one thing I'd say almost never works for reading code, though, is the thing people seem to insist is best practice: scattering everything into a hundred separate files with no clear order at all!
Trying to understand that code is like sitting down to an encyclopedia and then being asked to somehow use it to answer to the ultimate question of life, the universe, and everything.
The worst is when you grep the code for "main" in an attempt to at least come to your own idea of order, and it turns out that a bunch of files have their own main functions for various unit tests in files the build system just happens to ignore :/.
That's part of why Knuth came up with Literate Programming: he wanted to be able to present the reader of his code with a coherent order that makes sense to understand the project.
Given the strict formal requirements on order of languages like Pascal, Knuth had to come up with a clever preprocessing scheme to satisfy both the reader and the compiler. (See his tool, https://en.wikipedia.org/wiki/Web_(programming_system) )
Modern languages are a bit more flexible, but can still benefit from some re-ordering.
I used to use tools like grep a lot, but I found that my productivity really improved a lot when I set up an environment that supports 'jump to definition' and 'jump to references' etc.
I'm not sure what you have in mind, but if you put your "main" Python code inside a "main()" function, you can put that main() wherever you want (like at the top). You just have to call it at the bottom of the file, below anything it refers to.
That’s so interesting. I find myself organizing code to have minimum-understandable units, which ends up following the narrowing project->folder->file… abstraction all the way down - the end product resembles more a taxonomy than a story. I love your metaphor though and I am going to try it right away.
See https://en.wikipedia.org/wiki/Literate_programming
Perhaps reading code activates the same arras as reading prose in English, but running code in your head activates other areas
If you read code and don't think about what it's doing, are you really "reading" it?
Reading code without running it in your head feels like reading prose without actually comprehending it.
You can read (scan) code to get the general gist of it. It's more at the level of "this code looks at the pathname, then some cookies, and then either calls the signin function or returns True". That's about the same level where I read most prose. It's enough to answer the question "what does this do" (answer: "calls signin if you aren't logged in but should be") or "how complex is this" but not enough to modify the code or understand the intricacies of it.
What you are referring to is simulating the execution in my head to figure out which execution flows exist, figuring out which cases aren't covered, what the function calls actually do, what the significance of those cookies is, etc. That's similar to how I read contracts. But unless I have to write a literary analysis or somebody asks me to find all the plotholes and inconsistencies I don't read normal prose that way.
It might be interesting if there are similarities between programmers tracing execution flows, lawyers reading an unfamiliar contract, and editors finding inconsistencies in short novels.
But what participants in this study were actually asked to do is:
So "this code looks at the pathname, then some cookies, and then either calls the signin function or returns True" seems to align with that.
I'd put most of my code reading much closer to "inferring intention" than to "running in my head". It's really more like navigating through a complex building, looking for certain rooms than simulating execution. "running in my head" is to reading code like "pronouncing in my head" is to reading prose. Both aren't the norm.
Sometimes working out the details what is the right output of a piece of code (like, in the line x = f(15), is x 2345 or 2346?) is very time consuming
It's also sometimes unnecessary to understand the high level picture of what the code does (like "oh, this computes the GCD using Euclidean algorithm, I had to code this in uni once")
So, most people read in a higher level fashion and understand just fine. It's really like reading math. When you read 23443 + 54454 * 454534, do you need to work out the computation to understand what this does?
You can read code line by line and understand what each line does, but any algorithm that has more than 5 lines of code probably needs an additional step where, after reading it line by line, you need to take a step back and think about it in a different way to understand what the whole block of code is trying to do.
Maybe? I don’t need to read and calculate every iteration of some loop to understand that it’s mapping. While if I need to determine the actual output value of a function, I might.
A lot of code doesn't _do_ anything. And you can still read it.
Eg I'm thinking about type declarations, or constraint based programming, etc.
Reading code and not running it is like reading a Spanish text but not knowing Spanish. Running it is equivalent to comprehension.
Compilers understand code pretty well, but they don't run it. (Similarly, if you are a human translating code from C to Pascal, you'll want to understand it, but you won't necessarily execute it by hand to get that understanding.)
How could you run code, when you don't know the inputs?
You can reason through how the code could run with some example inputs, but that's just one of many tools we have in our belt to comprehend code.
In eg Rust or Haskell just looking at the types is pretty useful. Or in linear programming, you might want to think about the constraints expressed, but not actually do any arithmetic yourself.
I’ve never seen a compiler that can answer the question: “what is the purpose of this function?” On the other hand, if I ask a human that question about a particular function and they are unable to answer it satisfactorily, I would have an extremely difficult time believing that they understand it.
Humans don't necessarily run the code step by step in their read to answer this question, either.
Quoting again the part that that prompted the discussion:
The question wasn't about whether the programmers understood the code but whether they can predict what the code will output.
I hypothesize that either the programmer recognizes the purpose of the code or they don't.
If they do recognize, their brain will probably engage with the code differently, in a more high level way, taking into account the bigger picture; but if they don't they probably need to execute it step by step to have any chance of predicting what they do, which is akin to doing a calculation.
It also depends on whether the code is a tangled mess or well structured; how descriptive are function names and variable names; whether the code has comments; etc.
And of course in real world code there is a mix of both modes of reasoning. And the point is, those two modes of reasoning might as well activate different regions of the brain. (or maybe not?)
Well, it also depends on whether the suspect that the code has a bug.
Normally, we try to understand code by taking shortcuts through function names and structure, and fill the rest of in via pattern matching.
But if I suspect that a piece of code has a bug, I work hard to turn off these higher levels and concentrate on what's actually written.
Sure, but your human doesn't necessarily gain that sense of purpose by executing the function in their head. More likely, they are looking at the name of the function and its arguments and return values first, and work from there.
I wasn't arguing here that any existing compiler shows a human level understanding of code. Just that there are many ways to understand code, and executing in your head is but one of tools in your arsenal.
Interpreters run your code, but they don't 'understand' it any better than compilers, which don't run your code.
In a sense, compilers typically 'understand' your code better, allowing them to do more optimisations.
(The boundaries in practice are more blurry.)
That would already support the thesis, because formulating and understanding natural language share quite a bit.
Different, but not entirely different, both use the same kind of reasoning about program behavior. And the article is not about writing code, other than to the extent that it should be comprehensible by others.
Lots of people doubting this, and saying running === comprehension.
Here's an exercise for you: how much did Bill spend at the grocery store?
Bill and Tom went to the show store, and Bill bought a black pair of shoes for 23.56. Tom got a pair of red shoes for 40.30. Then they went to the grocery store, and Tom bought a loaf of bread for 3.50 and a gallon of milk for 5.99. Bill also bought a loaf of bread but didn't get any milk.
Anyone can tell that answering that specific question uses a different part of the brain than answering "what did tom and Bill do?"
And further uses a completely different part than: "modify the story to add a barbershop visit for Bill after the shoe store" which will require parsing the grammar to inject an extra story and keep things consistent.
Big picture !== Small details !== Writing !== Editing existing
The study feels incomplete if the four types of understanding are not being equivalently asked for both a story and the code.