The US Torture Bill as C code

Slightly politcal, but the boingboing commentary is simply hilarious from a PL point of view.

From my perspective the joke is on a deeper level. You see, it's simply that C is torture.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

lol

nice thread... :)

amazing to see so many clueless java guys...

you mean clueless about how

you mean clueless about how clueless c programmers/designers are ? ;-)

OK, I'll Bite...

...why are the Java guys clueless? I'm assuming that you know that in Java, "==" is a test of object identity (Integer a = new(42); Integer b = a; a == b -> true whereas Integer a = new(42); Integer b = new(42); a == b -> false) and the "equals" method, which is defined on class Object and therefore inherited and/or overridden, performs structural equality testing unless Object's implementation is used, in which case it does "==". So the Java guys claiming that this is a C/C++ issue (ignoring the political pun, obviously) are exactly correct.

Update: I neglected to point out that Java also disallows the "if (foo = bar)" construct that is the basis of the pun in the first place, i.e. one of the real improvements of Java vs. C/C++ lies precisely in correcting this ancient egregious boneheadedness on the part of C and C++'s designers.

"correcting this ancient

"correcting this ancient egregious boneheadedness on the part of C and C++'s designers"

hey! it isn't a bug, it's a feature: some people like syntax shortcuts, like having the value assigned to be the value of the assignment expression itself. :)

That's of coure the point.

That's of coure the point. Since some shortcuts are ok, and some not worth the risk, designing languages isn't a trivial exercise. Some languages go out of their way to make things explicit (does Ada ring a bell?), and this is probelemaitc for a host of different reasons. So when (and how) do you draw the line? It seems silly to insist on the validity of general prinicples ("bondage and discipline", "dynamic languages" etc.), rather than trying to assess the real costs and benefits.

I think it's a good exercise to consider the specific problem here raised by this example, namely should assignment be an expression or not. It's not black and white. But history shows, in my opinion at least, that the C choice was the worng one.

of course...

"should assignment be an expression or not"

...in an ideal world, there should be no assignment expressions... ;)

Heh

I knew that'd get a response. In more fairness than in my previous post, I actually like the idea that expressions have values (hey, I'm a functional programmer; it'd be weird if I didn't like that). It's really only the coupling of expressions having values and the weakly-typed aspect of "any non-zero value is equivalent to boolean true and a zero value is equivalent to boolean false" that causes problems here.

Of course, a good C/C++ compiler will also let you indicate that the construct in question should generate a warning or an error; the fact that this isn't mandated by the standard can be taken as a good or bad thing as well.

So which is the "real"

So which is the "real" problem in the design of C?

For the record, while I hate the C choice regarding booleans, it's not really weak typing (as I am sure you know). It's a dumb decision, and the type system is not rich enough - but that's not where you find C's weak typing.

Actually

Although treating non-booleans like booleans is a problem (imho), the real problem here is that the symbols = and == are major typo victims. If the symbols were different, say, := for assignment and == for comparison, then some people may still write if (a := b) and treat the expression as a boolean, but only when they really mean it.

I too like expressions that have values, but I've never seen code like funcall(a = b).

I'm With Koray

IMHO, the design error was indeed using a symbol generally understood to mean "are these two things the same" (=) to mean "set one value to another." Pascal didn't make this mistake, Smalltalk didn't make this mistake... it seems most language designers understood that assignment was something that really needed its own syntax. I always appreciated, for example, Scheme's convention of ending side-effecting function names with "!", e.g. "set!" to remind the programmer that they're doing something risky.

Personally, I think they are

Personally, I think they are all errors. I think it boils down to two questions: (a) which is the most severe problem, which can be read as meaning which issue causes the most bugs, and (b) you can solve the original problem by making various chnages to the language (since the problem results because of the combination of several features), which changes would make the smallest disruption and produce the highest gain?

most severe

a) I think the auto-coercion issue, though important, is irrelevant to the discussion. The real error is assignment being an expression. In "if (a = b)", a and b can be booleans. No coercion occurs, but the error is still there.

I'm with Koray too

A set! expression in Scheme has a value (unspecified, but nonetheless) and for the purposes of conditionals, any value except #f is considered a true value.

I have never seen a Scheme programmer, including in my several years of teaching introductory CS in Scheme, write (if (set! ...) ...).

Oh! I have done that. But it

Oh! I have done that. But it was on purpose so I guess it doesnt count.

Smalltalk assignment...

...originally the Smalltalk assignment was a left pointer arrow (←). But since it's not in ASCII and not on the keyboard, I assume they borrowed from Pascal (:=). Be nice if our set of available glyphs was a tad larger.

Oh I miss my 3270 terminal...

...with its APL keyboard. But now we have unicode, and plenty of text editors that support it, there's no excuse for not having more programming languages that make use of it.

hmm... <- works just fine to

hmm... <- works just fine to me... ;)

<- == Less Than or Minus?

Never did get around to finishing my chart mapping APL to J... From a mathematical glyph standpoint, it's pretty rare to use two character symbols. From a PL standpoint, not having those extra characters on standard keyboards has limited the appeal of APL for some time.

Of course, there's always the question of whether languages like APL and J are too symbol rich. Does it make code easier or harder to comprehend?

Of course, there's always

Of course, there's always the question of whether languages like APL and J are too symbol rich. Does it make code easier or harder to comprehend?

I tried to learn J but found it too arcane. I'm sure if you live and breathe it that it's great, but I don't have the patience these days to learn a symbol heavy language. J seemed especially hard because the meaning could shift quite a bit depending on the context.

So, in the end it all boils

So, in the end it all boils down to a small syntax tidbit and people's unwillingness to accept that = and == are different operators in C, right? ;)

You known, if i was unaware of Pascal's syntax and typed:

if (a = b) then ...

assuming it would behave the same as in C (assignment expression returning the value assigned), i'd get a big logic error. Without any warnings from the compiler, since it's a perfectly correct pascal expression.

In the end, i believe lack of familiarity with a language is the biggest prejudice against it. The "if (a=b)" errors are really only common with novices or, as the java guys showed, people unaware of C semantics...

Interesting Point...

...but it ignores the fact that "=" already had a semantics before the first programming language was invented, so essentially all C programmers bring an intuition about what it means to their programs. And again, the issue isn't really programmers "getting it;" the issue is how easy it is to typo between "=" and "==".

Your claim that the Java guys were unaware of C's semantics is bizarre in the extreme: do you really mean to say that of James Gosling and Guy Steele? They are all too well aware of C's semantics—they just deliberately rejected some of them and, more importantly in this case, one very questionable syntactic construct.

I think he meant the Java

I think he meant the Java guys in the boingboing thread.

Perhaps...

...but I still don't see that it follows from the comment thread. On the contrary, most Java programmers are perfectly familiar with the =/== trap and are happy that it's a non-issue in Java. So I continue to find the point odd: an entire class of errors that frequently occur in C/C++ simply aren't possible in Java, and when Java programmers point it out, they don't get C semantics? Huh?

"frequently"

What's lost in this discussion is that =/== almost certainly isn't a "frequent" error. I occasionally make this typo myself, but gcc -Wall warns me about it, and I correct it. I never see this error at runtime.

Developing C code without the "-Wall" compiler flag is like writing large Perl programs without "-w" or "use strict". Sure, you can do it if you want, but why do so when it's so easy to avoid hurting yourself?

Mostly Right...

...in the sense that most people can probably use GCC these days. But it wasn't always thus, alternative compilers still often don't warn about the construct, and in any case it's not required by the standard. It's nice that some tools make an effort to deal with the problem, and I certainly agree that it's foolish not to take advantage of such tools when you can.

The fact remains, however, that most non-C/C++ languages simply don't have the problem and never did, leaving the question as to the value of the constructs that lead to the problem in C/C++ open.

design time

It's easy to dismiss the syntax shortcuts C allows a programmer in an age where keyboards are soft and IDEs assist you in writing code and even providing code skeleton templates for you to just fill in. But such luxuries were not available in the C/Unix environment when their designers were working on them. Hard-to-type teletypes and basic, crude line editors were the rule of the day. People surely felt enamored by C's simplicity and, yes, reduced typing the shortcuts allowed.

I believe it also has something to do with the ammount of C code written vs pascal code since those days...

and yes, i was referring to the posters at boingboing, not Gosling or Steele.

You can have it both ways.

I'm surprised no one has pointed out the workaround that I usually use:

(1) turn on your C/C++ compiler's warning about "assignment in conditional expression"

(2) rewrite "if (foo = bar)" as "if ((foo = bar) != 0)"

voila: you have lost no efficiency but no longer have the risk of accidental assignments in this context.

Unfortunately, the workaround I usually SEE is the loathsome "put the constant on the LHS", e.g.,


if (CONSTANT == foo)

which I find to be bizarrely unreadable...

Puzzled

Although writing it the way you suggested makes the intention clear, I don't think the problem is when people intend to write if (foo = bar). It's when they intend to write if (foo == bar), but produce if (foo = bar) via a typo.

The CONSTANT == foo addresses the very same typo. It's so loathsome that at a code review I was even told to convert a if (x == 1) into if (1 == x) to reduce the likelihood of the next maintainer committing a typo (I suppose there's a slim chance that he was going to delete one of my ='s). Code reviews are fun.

What he's saying is that if

What he's saying is that if somebody does do a typo, they will get a warning. And to avoid the warning if they really want to do an assignment, they can use the more explicit syntax. So as long as you keep the warning on (and don't ignore them!) and follow this convention you shouldn't get bitten by this bug.

Though I agree with Paul -- the existence of this bug highlights many of the sharp edges of C.

Ah

I wasn't reading it with my head. Thanks for the clarification.

Hm, if I were a pacifist (or

Hm, if I were a pacifist (or anarchist) I'd simply "#define terrorist 0".