Modeling How Programmers Read Code
synesthesiam.com
synesthesiam.com
I find this contraint interesting - I don't know if computational thinking is a strength or a weakness. Increasingly, it seems that computational models occur naturally and therefore the ability to think in such a manner would have inter-disciplinary value.
If we deem it a weakness, then programming becomes a UX problem rather than language one. The lack of change both within and across programming paradigms would suggest that many don't believe this to be a fundamental issue.
A good programmer also needs to be able to effectively communicate through code to both others and themselves, know how to design maintainable programs, how to preemptively avoid bugs by making their code harder to misuse, and too many other skills to list here -- and not all of those naturally flow from knowing how to think like a computer.
This is primarily hard because we're wired for fuzzy mental abstractions, since they make loads of tasks (natural language, making breakfast, manual labor) far easier compared to taking genuine formal approaches, and we have a lower layer of the brain that can be trained to follow exact procedures quite well anyway.
EDIT should have RTFA before commenting, gaze tracking stuff is very cool
I would think we could do much of this already if we tried, but there are a lot of things on my list to do until I get to that.
When there are no domain restrictions, computers have not proven very capable of comprehension. Look even at the comparatively simple domain of handwriting recognition.
More importantly, you entirely miss the problem that many times the human doesn't know exactly what he wants until he sees it.
As a software engineer, I have no fear my job will be replaced by computers talking to product managers.
Daily or weekly, feedback nice and quick
In a lecture about this topic (how to create specifications that can be turned into formal correct code) we were given the following simple example of an incorrect specification:
"Everybody loves my baby. But baby loves nobody, but me."
If you formalize this, you can simply conclude that the person that says that is equal to the baby - which clearly is not, what you intended.
And this is a very, very simple specification. Specifications of real software are magnitudes more complicated.
It's partly a matter of giving the objectives to the computer at progressively higher levels, and partly a matter of improving user interfaces so that you can tell what the thing is doing and what it's going to do.
That is, having computers write code depends on the code being in a form about which computers can formally reason. If you can't prove anything about your code because the language is that bad, good luck getting a computer to write code.
/explain_the_joke.jpg
To address (some of) your specific point, I suspect part of the appeal of functional programming languages is that they naturally promote describing the data flow of the code. In contrast, imperative languages inherently dwell on control flow, even though it’s often an unimportant implementation detail. It turns out that even when we’re reading imperative code, we’re trying to figure out the underlying data flow anyway, so why not cut out the middle step?
I also suspect part of what holds back functional programming languages from wider acceptance is that when you’re modelling something where time/order matters, the control flow is not an unimportant implementation detail. You have to work harder to describe it in a functional language where you get a lot for free with an imperative programming language.
This isn't necessarily true. In Haskell you can use do blocks like:
main = do
action1
action2
...
and your actions will happen sequentially. This is just syntactic sugar behind "action1 >> action2". The real reason for the special syntax is when the actions also return a value you can do "x <- action1", and use the variable x. This is still just sugar, but the unsugared version gets messy pretty quickly.
The big difficult in going from imperative to functional languages is thinking about data structures as immutable. You go from asking how do I change the value to asking giving this value, how do I construct a new value.
Monads in Haskell were exactly the example I had in mind when I wrote my previous post. As you say, you can use ‘do’ notation in simple cases, but it’s just syntactic sugar and the unsugared version quickly becomes unwieldy if you need more flexibility.
Edit: A good case study is the not-quicksort quicksort that gets used all over the place as a demonstration of Haskell’s elegance. Something closer to a real quicksort is rather less tidy: http://www.haskell.org/haskellwiki/Introduction/Direct_Trans...
The big difficult in going from imperative to functional languages is thinking about data structures as immutable.
That’s certainly one of the big jumps, but I don’t think it’s the whole story. You can do a lot with purely functional data structures, given a bit of time to get your head around them, but sometimes you might still have good reasons to work with mutable data instead. That can be very clumsy when shoehorned into a primarily functional programming language.
I’m hoping that one of the next big steps forward in programming language design will be providing much better control of externally observable behaviour, but without forcing a purely functional style or requiring prohibitive amounts of boilerplate code. I’d like to program in a style that is declarative by default and provides powerful tools for working with functions, but also with the ability to break out of that immutable world in controlled ways as easily as writing imperative code and as safely as writing code with a good type system today.
I've actually found that it's much better to compose monadic functions with (<=<) than use long do blocks. It forces you to structure your code much more appropriately.
It especially annoyed me when he praised Eric for going back to understand the function first, when that function isn't even present in the novice's program.
Very interesting reserach though.
Really? How about "adequately understood the function and did not have to reread it". We are humans, not compilers. ;)