Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

All it means is that he understands C better than other languages. Even Java (yes, Java) has these rhythms that he speaks of. You look at code and you feel the logic, even the necessity of it. That's just the feeling of being in tune with code and with the person who created it, thanks to a shared understanding of the language. Master any language and you'll get the same feeling when you read well-written code. Actually, though, the less boilerplate a language forces you to write, the less you'll feel that "inevitability," since much of the "inevitable" structure of the code -- the predictable patterns in the design of code, or, one might say, "design patterns" -- is code you shouldn't have to write in the first place.


C is the language some may love to hate, but an experienced developer will create clean, concise code. I remember reading through cifsd [1] by cinap_lenrek and thinking, ``my god, this is beautiful''. No boilerplate, just straightforward code. And yes, unobtrusive error handling.

Also, a blogpost post comes to my mind: ``A Timeless, Desert Island Language'': `And that's why I'd choose C as my desert island language. Because in less than 10 pages of C, I can bootstrap a basic Lisp interpreter (...)'.

--

[1] http://plan9.bell-labs.com/sources/contrib/cinap_lenrek/cifs...

[2] http://www.findinglisp.com/blog/2008/06/timeless-desert-isla...


My basic Lisp interpreter was six pages of C, but it's really not usable; it responds to almost any program error (including searching for nonexistent variables) by dumping core. http://lists.canonical.org/pipermail/kragen-hacks/2007-Septe...

Darius Bacon's https://github.com/darius/ichbins is a Lisp-to-C compiler written in itself. It includes an interpreter written in C to bootstrap it — ten pages: https://github.com/darius/ichbins/blob/master/boot-terp/lump... — but the actual compiler is only six pages of Lisp.

My somewhat more performant (but less complete) Scheme-subset-to-assembly compiler is more like 30 pages: http://www.canonical.org/~kragen/sw/urscheme/

If your desert-island language is the one in which bootstrapping your high-level language of choice is the easiest, it seems like you'd probably be better off with Haskell or ML.


>... I can bootstrap a basic Lisp interpreter

That sounds like an argument for any language, though. As long as you can build the language of your choice in language X, you're fine being stuck with X because you're not really stuck.

If they had to write absolutely everything in more "pure" C, would their tune be the same? I think C is a fine language, but it's missing some significant niceties. Like a decent native string class.


> That sounds like an argument for any language, though.

Not really. Unless the language gives you access to the computer (either directly, or by emitting machine code and scheduling for execution), you'll have hard time implementing it efficiently. Compare IronPython (python implemented in python) with the mainline Python (implemented in C).

Yes, there are meta-circular interpreters. But that's not the holy graal.

> I think C is a fine language, but it's missing some significant niceties. Like a decent native string class.

C++ is what happens when you sprinkle a few niceties here and there. The C++ Faq Lite [1] is longer than the whole C specs. The kitchen sink language can do everything, but porting it to a new environment is quite a task. Never mind the compilation time.

You can get an optimizing C compiler [2] in less characters than C++ Faq Lite has.

If you want modernized C with niceties, (Google's) Go probably comes close enough. No string class, thou, just string type.

--

[1] http://www.parashift.com/c++-faq-lite/

[2] http://gsoc.cat-v.org/projects/kencc/


>Not really. Unless the language gives you access to the computer (either directly, or by emitting machine code and scheduling for execution), you'll have hard time implementing it efficiently.

Why not use Ruby to emit a bunch of bytes (ie, assembly), push it into a file, and set the executable bit? Ruby could be used to create GCC so you can write C. ie, a Ruby-based Ruby-to-assembly compiler. With that technique and therefore technically Ruby alone, you're still capable of recreating every language or application in existence, right down to being exact binary duplicates.

Sure it's pedantry. But the entire hypothetical deserted-forever-with-one-language situation is pedantic at its core.


+1 C is ugly.

- Why do I need to typedef a struct to make it look like any other type?

- Why do function pointers look so bad?

- Error handling in C? Those goto exception; if(0){exception:} sure look fantastic.

- int* var1, var2; var2 is an int, not an int* ... The language lets you stick the * right next to the type as though it modifies the type. Which it does in casts. (how do I escape asterisks on here?)

- A system language where int can be 32 bits or more.

And probably more from people more experienced in C than me.


- You don't. C99 treats structs like classes.

- Typedef them.

- If done right, it can be quite unobtrusive.

- That's not how it should be written. This is a 100 times clearer:

int *var1, var2;

- Not really. And don't use int, int32_t is where it's at.


"- That's not how it should be written. This is a 100 times clearer:

int var1, var2;"

Somewhat aside from the actual article, but this might actually be the least clear way to write a definition, since the pointer marker appears to belong to var1, but not the overall definition of int. Here is how I would automatically read the definitions:

"int var1, var2;"

Of type int (variable), create var1, var2.

"int var1, var2;"

Of type int and type * (pointer), create var1, var2.

"int var1, var2;"

Of type int, create pointer var1, pointer var2.

"int *var1, var2;"

Of type int, create pointer var1, default (variable) var2.

Not sure how this works for and against C, since the language definition is really old at this point and by the standards of its time C is really clear. But languages have moved on and a standard has emerged over the intervening time that is a bit more logical.

Also, I think this article is a real piece of fluff :).


    int *var1, var2;
is not clear at all. var1 has type "int pointer", and for each type T, its pointer type is represented as the type T*. It's just one of the many ways the C user interface is broken beyond reason.

The point is not that you can't do good things in C. The point is that it is very easy to do bad things in C. A good UI makes good things the natural way to do things, and actively discourages bad things. C's UI is the opposite.


It's just one of the many ways the C user interface is broken beyond reason.

I'd say this one is just a question of preference. I happen to like to be able to declare my variables together with my ponters.

A good UI makes good things the natural way to do things, and actively discourages bad things. C's UI is the opposite.

In my opinion, that's the beauty of C: unlike Java (and, to a little extent, C++) it doesn't dictate how you write your programs. You are free to shoot yourself in the foot, but you also get to decide exactly how you want your code to look and feel.


The small cost of not being able to declare your variables together with your pointers is nothing compared to the confusion it avoids.

    int* var1;
is the way I (and I suspect anyone who's studied theoretical algebraic data types) think about my variables and types. It sucks that C forces me to mentally translate it to a much less satisfying form.

I'm not sure what being ridiculously easy to make errors in has to do with dictating how to write your programs.


C's designers agree with you about the notation for types and declarations, which was one of the things they fixed when they designed Go.


Well, OK... C is ugly. That doesn't hinder that it is also beautiful.

I did C for ten years, on and off. I stopped. C is an old love where the break up wasn't bad, it was just me that changed.

I realised what I really liked -- to get shit done! That is, to take an idea or a specification and make it exist in the "real" world. That implies the importance of speed, so I can get to the next idea. C just isn't for maximising speed of development, unless for really low level stuff.

Sometimes, I mourn a bit for what could have been.


I can sympathize with the author about C, but with Java... Every time I need to figure out a Java program, I end up being in almost physical pain. Huge trees of empty nested directories and files with nothing but method definitions that do nothing but return a property... or, better yet, tons of empty functions called pure virtual.

It's hard to feel the logic and necessity of code when you can't stop being flabbergasted why the language has to be so verbose and complicated.

I admire Java as an environment, but am scared shitless of it as a language.


But those aren't really problems with Java - they are problems with the idioms common amongst Java developers.


Exactly, and C is the worst offender for boilerplate code. There isn't even a list abstraction! It's surprising that there's an array abstraction and that people aren't just forced to use pointer arithmetic.


This is not fair. C was (and still is) intended for situations where writing your own list abstractions is the right thing to do.

Unlike lists, the array abstraction doesn't cost anything, as it's just straightforward pointer arithmetic underneath. This is why it is in the language.


There are list abstractions in libraries.

See the Linux kernel's list.h for a very nice and generic linked-list implementation.


Occam's razor. Keeps things simple and beautiful.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: