
Stress impairs cognitive functions - The loss of those functions can explain why programming is hard - nickb
http://the-programmers-stone.com/about/
======
cturner
That series of articles may be the most significant thing I read this year.

I have a comment on one bit:

    
    
        In his article The Perils of JavaSchools, Joel Spolsky
        refers to "programmers without the part of the brain
        that does pointers or recursion". In this "ha ha only
        serious" comment Spolsky displays a profound intuition.
        He's obviously observed his teams very carefully. My
        only disagreement with him is that I know from
        experience that everyone has the necessary bit of the
        brain. It's just that understanding pointers and
        recursion requires juxtaposition, and in most people
        that mode is not accessible.
    

_The pointer problem_

I am a programmer who tried and failed to get pointers many times over the
course of some seven years, and then consciously tried a new way of thinking
about it that flicked a switch in my mind nearly instantly. I was aware of the
widespread belief that you either did or didn't get pointers, and immediately
wrote down everything I could about the situation in order to capture it. I'll
describe my findings and the situation here.

Pointers are easy when you think about the program in terms of memory and
what's actually going on: casting of ints. The problem for me was that my
brain was filtering out the correct scenario because due to a contradition in
the syntax. Let me present a simple example to use for discussion.

    
    
        #include <stdio.h>
        #include <stdlib.h>
    
        void fn(char *c) {
            printf("[%c]\n", *c);
        }
    
        int main() {
            char *c = malloc( sizeof(char) );
            *c = 'a';
    
            printf("start\n");
    
            fn(c);
    
            return 0;
        }
    

One of the things that kept screwing me up with pointers in C was the
contradiction in the situation where you pass a pointer to a function, yet the
function receiving it has a different symbol for it. Look at the example above
- where we declare 'c' in the parameter list for the function 'fn' it has a
star next to it. Yet when we call fn it doesn't. But ... those are the same
thing. How can that be?

I found that the more I thought about the problem the less I'd understand it.
I tried to get several friends to step me through it and couldn't get there.
I'd actually get it for a while, and then I'd lose it. In desperation - and
I'm not making this up - I worked out a series of base examples that I knew to
work even though I couldn't see why, printed them and pasted the sheets into
the back of a copy of _Systems Programming for SVR4_. Horrifically embarassing
- a professional unix-based programmer, who hangs around real geeks, who has
designed and implemented several successful applications on a variety of
platforms - reduced to this. I rapidly reached the point where I could write
_and debug_ C code without my colleagues detecting the weakness through my
system. A key part of it was knowing the exact point at which I had to
actively stop thinking about the syntax and trust what was written on my base
examples.

OK - step back a bit. There's something else that's important. I'm told that I
spoke early when I was a child, and rapidly got to the point where I could
hold court in a room full of adults, and talking at their level. English was
my strongest subject throughout high school. Throughout my life people around
me seemed to think I was very smart but I felt like a fraud because although I
was qite quick in language stuff, there were some problems that kids who
struggled in general got quickly and that I didn't.

Early last year I was struggling through what felt like just such a problem
and noticed myself feeling at a loss without an example to leverage. I
wondered why it was that I needed to learn from example, and thought it
interesting that some people are able to work through things without examples,
yet I seemed incapable of it. This caused me to create a theory that I had a
strong skill at certain sorts of learning based on pattern matching, and that
overuse of this skill had stunted other learning skills. I told myself that
I'd look out for opportunities to solve problems without using this kind of
approach.

The first decent example that came up over the next few days was -
conveniently - the pointer problem. A friend called me up to say she had an
exam the next day and needed help with C - could I help? Readers will already
recognise that are few times in any lifetime when good looking, charismatic,
single girls (this one is a superb singer as well) will seek you out on the
strength of your reputation for coding and I replied in a steady voice and
pace, "Sure - why don't you come over now?" As I hung up I thought - oh oh -
back to that old pointer problem that has been haunting me since the beginning
of time. But then I realised that this was the opportunity I'd been looking
for to overcome a problem with non-example based learning.

I had the whole problem solved less than five minutes from putting down the
phone. I dug up my copy of _The C Programming Language_ and read the section
on pointers to refamiliarise myself with the problem space. As you would know
- the problem in a world without pointers is that you can't change non-global
variables within a function so that the change persists past the end of the
function (I had always been fine with this - nothing new so far). So I moved
to the next step and decided to ask myself, "how would I solve this?" Easy -
pass in the memory address. Have a mechanism for referring to memory addresses
in memory instead of the variables they contain. Oh, and there needs to be
some syntax to be able to dereference a variable.

That was the lightening bolt moment. The problem with pointers in C is that
the [star][varname] syntax means two different things, and they are actually
contradictory from a certain perspective. In one context it means "declare a
variable that is a pointer" and in the other it means "deference". Whenever my
languages-brain bit looked at this it couldn't deal with it, recognised it as
a contradictory positions and basically shut me down, but not in a way that
let me work out what was going on. Have a look at it yourself from that
perspective - hopefully you'll see what I always did. _Now_ whenever I look at
C code I instead just think "everything is an int and pointers are all about
casting ints, and a star when you declare something is your way of telling the
compiler that the type of this thing is int-pointer instead of just int". Thus
I now have no difficulties at all.

When I was at uni I heard the whole thing about people not knowing C would
never be Real Programmers. And I'm glad I stayed insecure about it, or I may
never have conquered what is clearly a huge deficiency in my learning
patterns. OK - that's enough about me. Let's instead look at the big picture.
The assumption behind the claim that groking pointers is a good guide as to
whether someone has what it takes is that in order to get C you need to be
able to think like the computer. But could it in fact be the case that the
emphasis on C in computer science has been driving people with a strength in
the humanities _away_ from programming (in preference of people who do not
have a language dominance) for the last few decades, and causing bias towards
people who lack whatever it was that was sitting in my brain filtering out the
correct case?

Oh - the short conclusion of my story is that - girl came over, we spent all
night pretending to be a C interpreter by drawing memory diagrams on my
whiteboard, she moved from likely failure to a reasonable mark in the space of
four hours, was thrilled after the exam the next day, and now we both live on
different continents.

I think there are leaps in what I've written here. But I'm confident I'm on to
something about the relationship between people who use a certain type of
thinking and have trouble with pointers. It probably doesn't apply to people
with a strong background in low-level programming.

~~~
alxv
And if you change your example only slightly, you can break again most-
people's mental-model of pointers:

    
    
        #include <stdio.h>
    
        void fn(char *s) {
            printf("[%s]\n", s);
        }
    
        int main() {
            char *s;
            s = "hello world";
    
            fn(s);
    
            return 0;
        }
    

And yet again:

    
    
        #include <stdio.h>
    
        void fn(int s) {
            printf("[%s]\n", (char *)s);
        }
    
        int main() {
            char *s;
            s = "hello world";
    
            fn((int)s);
    
            return 0;
        }
    

And back to a single char:

    
    
        #include <stdio.h>
    
        void fn(char *c) {
            printf("[%c]\n", *c);
        }
    
        int main() {
            char c = 'a';
    
            fn(&c);
    
            return 0;
        }
    

The ugly and evil way:

    
    
        #include <stdio.h>
    
        void fn(char *c) {
            printf("[%c]\n", c);
        }
    
        int main() {
            int c = 'a';
    
            fn((char *)c);
    
            return 0;
        }
    

And the obvious way:

    
    
        #include <stdio.h>
    
        void fn(char c) {
            printf("[%c]\n", c);
        }
    
        int main() {
            char c = 'a';
    
            fn(c);
    
            return 0;
        }
    

It is not difficult to see why most people find pointers in C confusing.

~~~
queensnake
_This_ will blow people's mental models of _C_ (genuine example):

    
    
        #include <stdio.h>
    
        int main()
        {
           char const* c = "hello";
    
           // this is the interesting bit - n[c] == c[n] (n = number literal) !!! I swear, try it.
    
           printf("This program compiles and prints:'%c %c %c %c %c'\n",
              0[c], 1[c], 2[c], 3[c], 4[c]);
           return 0;
        }
    
        // See? I read that both forms are translated to *(c + n), 
        // which explains the equivalence. Weird, no?

~~~
alxv
_See? I read that both forms are translated to_ * _(c + n), which explains the
equivalence. Weird, no?_

Well, that surely is evil, yet perfectly valid C code. But personally, I don't
find it surprising. Of course, you need to grok what A[n] really is -- i.e.,
syntactic sugar for *(A + n), as you just explained.

~~~
schtog
which is the same as *(n + A)?

------
ecuzzillo
I don't buy it. Stress has nothing to do with getting kicked out of hack mode.
Even the least stressful of interruptions, assuming it uses the local state
registers that are used in hacking, can completely scramble your brain. The
friendliest of comments from co-workers, assuming they're about hacking (but
not your project) and require hacking thinking, can ruin it, if the comment
turns into a conversation that lasts more than 60 seconds.

It's not about stress. It's about juggling a bunch of delicate state, and the
state is being held in short-term memory registers that are easily clobbered.

~~~
eru
And now - please repeat the same with functional programming metaphors.

------
jey
So maybe there's some truth to this: <http://xkcd.com/323/> ;-)

~~~
MuddyMo
Now I have to stop reading Hacker News and clean up the soda I just spewed all
over my keyboard. Thanks alot, jey.

------
MuddyMo
Bravo! Bravo! Tour de force! Should be read at least once a month as an
antidote to creeping groupthink.

------
aswanson
If you learn hardware first, pointers are pretty easy. However, learning
hardware inevitably slants your thinking towards solving ALL problems in those
terms, which is bad for higher level architecture and design thought
processes. When all you have is a hammer...

