I’m not aware of many eye-tracking studies specifically, but there has been a lot of research done on the general subject of how we read and understand code. Search for papers on “program comprehension”.
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.
> You have to work harder to describe it in a functional 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.
> 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.
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.
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.