Extremeely basic programming question.

You can’t fool me, John Jacob Jingleheimer-Schmidt.

You’re right, that slipped my mind between reading the article and composing the OP:

As you state, that’s actually what they were looking for…the ability to hold to a consistent set of rules.

Here is a link that I promised a few posts above.

http://www.textfiles.com/100/famous.bug

This is the classic famous “Famous Bugs” document. It is a plain-text file from an earlier era (I first saw it in the mid-1980’s), consisting of a loosely collected compendium of disastrous programming bug reports. And yes, it includes some mentions of bugs that killed people, for example by fouling up high-tech medical equipment. There is one story of a space probe that was lost because somebody tried to send it a software update that caused the directional antenna to cease pointing back at Earth, thus losing all communication with it forever. It’s a kinda fun read.

Actually if you read the whole article (and its an interesting one, especially if you are ever in a position to educate or hire potential programmers), the point is to NOT give the test-taker any instructions for interpreting the code. Give him a group of very similar problems, and see if the results are consistent. Incorrect is OK, as long as the answers are consistently incorrect. If the test-taker is able to construct a consistent mental model of how assignment works (even if the model is wrong), that person has a much higher chance of successfully learning to program than someone who can’t.

(Bolding added)

This is an example of the discussion I wrote above, why there was a need for two separate symbols: One for assignment, and one to test equality. In the primitive FORTRAN days, the language didn’t permit such things (in particular, multiple assignments on one line), and a statement like:

A = B = C

was clear: It meant compute (B = C) (that is, compare B to C and produce a true/false result), and store this result into A (which is presumably a Boolean variable). With the advent of multiple assignment, as in Algol, this became ambiguous.

As for the <= symbol as assignment operator, mentioned by lazybratsche a few posts above: This idea has been kicking around for a while. The actual symbol <= could be a problem, as it also means “is less than or equal” in most languages. The above example
A = B = C
might be written: A <= B <= C and what would THAT mean?

As far back as the early Algol days in the late 1960’s, the symbol ← (arrow pointing to the left) was proposed as the assignment operator. Only problem was, computers in those ancient days typically only had some 48 to 63 characters in their entire character set, and ← wasn’t one of them. This is the same reason we use ⁕ (asterisk) for multiplication and not × (multiply-cross symbol) instead, even unto this very day.

Boolean (logical) results were represented in various ways in various computer systems. The idea that they should have standardized mappings to integers (0=false, 1=true), and that these values should be actually synonymous and interchangeable with integers, was considered by some (myself included) to be an abomination. C and successive C-like languages have perpetrated and continue to perpetrate this, whereas other stricter languages (Java in particular these days) have rejected that and maintain a wall of separation between Boolean and integer values.

The catch there is that a student might construct a perfectly sensible and consistent internal model that is nonetheless completely unlike any model the test-writers ever anticipated, and thus look to them like an inconsistent model (I’ve seen similar things happen, myself). This can be cleared up by talking directly with the student, but it takes a lot of time.

I did not have time to read the whole article, but I will find time to do that. What you’re saying makes sense, but may be a hit or miss approach. It would certainly uncover those who make excellent programmers. But I’ve found the most basic problem that determines programming ability is following a set of instructions in a step by step manner, just as a computer does. Some people aren’t able to set aside a intuitive feel they get looking at code. But beyond that, programming involves some higher level concepts that go beyond the step by step approach. I recall from glancing at the article that recursion and concurrency were mentioned, and those do require higher level conceptual models.

To understand recursion, you must first understand recursion.

This is the sort of thing that depends on which computer language is being used. Many (but not all) computer languages distinguish between an assignment operator (“assign to a the value of b”) and a comparison operator (“return TRUE if a and b are equal”).

In Pascal, which beginning computer science students learned back in the 1980s, “a := b” means the former and “a = b” means the latter.
In C and its descendents, “a = b” means the former and “a == b” means the latter.
In BASIC, “a = b” could mean either depending on the context, though the former would be short for “LET a = b.”

To understand concurrency, you must first understand both recursion and concurrency.

Got it. Thanks. (Wow, has a lot been posted in the time since I left work!)

This concept becomes clear if you think about what the compiler does at each step:
int i = 5; - causes the compiler to reserve memory sufficient to store an integer, then to set that memory to a value of 5
i = somethingNew; - sets the memory previously reserved to the new value

A subsequent statement of the form int i = 7; would cause the compiler to react as follows:
“You previously asked me to reserve space for an integer variable to be called i. If you want to assign a value to that, don’t include int, as this implies you wish me to reserve further memory. If you DO wish to reserve additional memory, don’t refer to it by a previously assigned name, as that leads to ambiguity and problems.”

Here are the models they considered (lines in figure 1 being the answers)

  1. Value moves from right to left (a := b; b := 0 – third line in figure 1).
  2. Value copied from right to left (a:=b–fourth line of figure 1, and the ‘correct’ answer).
  3. Value moves from left to right (b := a; a := 0 – eighth line of figure 1).
  4. Value copied from left to right (b := a – fifth line of figure 1, and a reversed version of
    the ‘correct’ answer).
  5. Right-hand value added to left (a := a+b – second line of figure 1).
  6. Right-hand value extracted and added to left (a := a+b; b := 0 – first line of figure 1).
  7. Left-hand value added to right (b := a+b – omitted in error).
  8. Left-hand value extracted and added to right (b := a+b; a:=0 – omitted in error).
  9. Nothing happens (sixth line of figure 1).
  10. A test of equality: nothing happens (fourth and fifth lines of figure 1).
  11. Variables swap values (seventh line in figure 1).

What other models are there?

With much disgust, I must respectively disagree about this concept becoming clear. In the plethora of programming languages that allow a variable to be declared and initialized at the same time, there are many different conventions about exactly “what the compiler does at each step”.

In the process of compiling, link-editing, loading, beginning execution, and continuing execution, there are several different points in time that the variable could be set to its initial value, with subtle and not-so-subtle implications. It also depends on the memory class of the variable (static, auto, or whatever other new-fangled classes certain languages provide).

The statement: int i = 5 ;
could produce subtly different results in different languages, and sometimes even in different implementations of the same language if the meaning is not specified precisely enough.

The pair of statements:
int i ;
i = 5 ;
is much more UN-ambiguous, and it is quite clear what result this causes. I think modern languages typically attempt to define the single statement: int i = 5 ; to produce the same result in all cases – but it gets confusing, I think.

I’m the wrong person to ask, because I’ve had such extensive exposure to mainstream programming languages that I’m conditioned to think of case 2 as “natural”. But I’d bet you that if you presented that question to a thousand folks who didn’t have programming experience, one or two of them would manage to come up with something not on your list.

It should also be noted, by the way, that C’s practice of using different symbols for assignment and comparison also has its dangers and pitfalls, in that typos can lead to valid code that isn’t what the programmer intended. The code snippet


if (i = 1) {
...
}

is perfectly valid, and will compile without errors (though some compilers will probably give a warning for it). It’ll set the value of i to 1, and then it’ll check to see if the value it just assigned is nonzero, and then it’ll run the conditional code.

Actually, come to think of it, I can think of another sensible way that


int a = 10;
int b = 20;
a = b;

could be interpreted. I could think, “Well, a and b are not equal, but the computer is trying to force them to be equal. I’ll have to adjust those values to make that happen, and it’s probably best to adjust them both by the same amount. So after I force equality, a and b will both be equal to 15.”.

This article might be of some help.

Indeed, the details can vary. I was attempting to describe what is typically happening “behind the scenes”.

Hey, that’s my name too!

What if you then asked them the same question except with 30 instead of 10? If they were consistent, they’d answer 25. You could say that the test marker would label those answers as inconsistent if they did not understand, but I would assume that over a number of questions they would pick up that a person was averaging the two.