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

It's not like C is famous for having particularly good syntax. If anything, it's the worst thing about it.


They must have got something good though. Else why would there entire families of C-like languages ?

Plus, to me C syntax is particularly good. You're writing real words and the computers does the things you tell it to. To the letter.


> Else why would there entire families of C-like languages ?

C became popular because Unix became popular, and when designing a language that intends to become popular one aims for a ratio of 10% novelty and 90% familiarity. Like, ever wonder why Javascript's date format numbers the months starting from zero and the days starting from one? It's because Eich was told to make JS as much like Java as he could, and java.util.Date numbers the months from zero and the days from one, which Java itself got from C's time.h. (Not coincidentally, Java and JS are both in the C-like language family.)

> You're writing real words

In C? Not compared to ALGOL, COBOL, Pascal, and Ada, you're not. :)

> the computers does the things you tell it to. To the letter.

As long as you're not using a modern compiler, whose optimizations will gleefully translate your code into whatever operations it pleases. And even if one were to bypass C and write assembly code manually, that still doesn't give you complete control over modern CPUs, who are free to do all sorts of opaque silliness in the background for the sake of performance.


To be fair with myself I was mostly snarking around op comment who dismissed the C language as if it was some ancient relic.

But even without accounting for compiler optimizations and cpu architecture, the C language just straight up lies to its user. You could code something entirely with void*.

PS: what I meant by "real words" is that you're naming functions and calling them by their name. Which in itself is very powerful.


> They must have got something good though. Else why would there entire families of C-like languages ?

Network effect. If you wanted to write for unix, you almost had to use C originally.

> Plus, to me C syntax is particularly good.

It's meh. It's not the most straightforward when defining complex types like arrays or function pointers.

> You're writing real words and the computers does the things you tell it to. To the letter.

So yeah, about that...


Everybody I know found it confusing at first, but its logical, and modular. I don't know a language with a better type declaration syntax. It gets impractical when you define function that return functions that return... because these expression grow on the left and right simultaneously. But realistically, you don't do that in C, and other than that, I find it easy to read the type of any expression...

    const int *x[5];
    *x[3];  // const int
    x[3];  // const int *
    x;   // ok - there is first a decay of x[5] to *x, so: const int **
Is there any other syntax that has this modularity?


> But realistically, you don't do that in C

IMHO, that's a self-fulfilling prophecy. If it were reasonably easy to do that in C, it would be done more.


It is quite reasonably easy enough compared to any real practical programming task. For example:

  // your ordinary function declarations
  int plus2(int i) { return i + 2; }
  int times2(int i) { return i * 2; }

  typedef int (*modfun)(int);
  // a very reasonable syntax altogether
  modfun get_modfun(bool mul) { return (mul ? times2 : plus2); }
Nests as well if you ever wanted to:

  modfun get_modfun_no_mul(bool mul) { return plus2; }

  typedef modfun (*modfun_getter)(bool);
  modfun_getter get_getter(bool allow_mul_opt) { return (allow_mul_opt ? get_modfun : get_modfun_no_mul); }


C is a systems programming language. It doesn't have closures or other features from functional programming. In other words, you can't "create functions at runtime". That is why you basically never see a function returning another function.


So, go is also a "systems" language, so the terms more or less meaningless now. Assuming you mean a language we can easily compile to an independent binary capable of being run directly on a microprocessor with no support, I offer you rust as a counter-example.

Also, functional programming and returning functions does not mean they are created at runtime.


It's a fact that C doesn't have closures. That is my point. I happen to like that fact, but you don't have to agree with me.

And "creating functions" means: closing over variables ("closures"), or partial application. I think it takes at least that to be able to return interesting functions.

(and whether go is a systems programming language is at least debatable. I think the creators have distanced themselves from that. It depends on your definition of "systems". You can't really write an OS in go).


> It's a fact that C doesn't have closures.

OK.

> That is my point.

Not unless your first two sentences have absolutely nothing to do with each other. Your point appears to be that because it's a low-level language it doesn't have these features, which is false.

> I happen to like that fact, but you don't have to agree with me.

Or I just think you don't have any experince using better languages. That isn't to say that other language could supplant C, but just that it's difficult for me to image actually liking the C type system (or lack thereof) and lack of first class functions. It's incredibly limiting and requires a lot of hoops to be jumped through to do anything interesting.

> And "creating functions" means: closing over variables ("closures"), or partial application.

Well, you said at runtime. Of course you can "create" functions at compile or programming time!


> Your point appears to be that because it's a low-level language it doesn't have these features, which is false.

I would think that first class closures do indeed _not_ belong in a low-level language. They hide complexity, and you want to avoid that in low-level programming. Not necessarily for performance reasons, but more from a standpoint of clarity (which in turn can critically affect performance, but in subtler ways).

> Or I just think you don't have any experince using better languages.

Nah, I have experience in many other languages, including Python, C++11, Java, Haskell, Javascript, Postscript. The self-containment, control, robustness and clarity I get from a cleanly designed C architecture is just a lot more appealing to me. The only other language I can stand is Python, but for complex things, it becomes actually more work. For example, because it's so goddamn hard to just copy data as values in most languages (thanks to crazy object graphs).

> It's incredibly limiting and requires a lot of hoops to be jumped through to do anything interesting.

It depends on what you are doing. It's a bad match for domains where you have to fight with short-lived objects and do a lot of uncontrolled allocations and string conversions. My experience in other domains (including some types of enterprise software) is more the opposite, though. Most software projects written in more advanced languages are so damn complicated, but do nothing impressive at all. They are mostly busy fighting the complexity that comes from using the many features of the language. But those features help only a bit (in the small), and when you scale up they come back and bite you!

Here's a nice video from a guy who gets shit done, if you are interested: https://www.youtube.com/watch?v=khmFGThc5TI

> Well, you said at runtime. Of course you can "create" functions at compile or programming time!

Closures and partial application are done at runtime. The values bound are dynamic. So in that sense, the functions are indeed created at runtime. I sense that you were of the impression that a closure would actually have the argument "baked" in at compile time (resulting in a different code, at a low level) instead of the argument being applied at runtime. That's not the case, unless optimizations are possible. If that was really your impression, this makes my point regarding avoiding complexity and that closures do not belong in a low-level language. (Look up closure conversion / lambda lifting)


I'm really not sure what you mean by "modularity". There's a lot of languages with much more readable and composable type declarations than C. For example in OCaml:

  let x : (int list ref, string) result option =
    let x1 : int = 0 in
    let x2 : int list = [ x1 ] in
    let x3 : int list ref = ref x2 in
    let x4 : (int list ref, string) result = Ok x3 in
    Some x4
The declaration of List.map:

  val map : ('a -> 'b) -> 'a list -> 'b list


I've got no issue with C syntax either, but to be clear, syntax != semantics.

To cut to the chase:

* syntax = structure

* semantics = meaning

C syntax would include things like curly braces and semicolons, whereas C semantics would include things like the functionality of the reserved keywords.

This SO answer gives a more detailed explanation:

https://stackoverflow.com/a/17931183/1863924


The nice thing about C is that it's a great cross-platform assembly language. I wouldn't call its syntax good or bad.


> The nice thing about C is that it's a great cross-platform assembly language. I wouldn't call its syntax good or bad.

Is it though? It's definitely available on a huge number of platforms, but are the implementations compatible?

And even if they are, there is so much undefined behavior that taking advantage of the cross-platform nature is not nearly as easy as it should be.


Exactly. If C hadn't been invented then someone would have invented it later under a different name.

Because it's obvious people need a minimalistic portable assembler.


Before C was invented there were already other companies writing OSes in high level languages, but yeah thanks to its victory now it gets all the credits.

History is re-written by winners as usual.


I wasn't thinking in terms of winners.

But what were those other OSs and languages? Sounds interesting!


You can start here,

https://en.wikipedia.org/wiki/System_programming_language

https://en.wikipedia.org/wiki/Category:Systems_programming_l...

Some examples, out of my head.

- Burroughs, now being sold as Unisys ClearCase, used ESPOL, later replaced by NEWP, which already used the concept of UNSAFE code blocks;

- IBM used PL/8 for their RISC research, before switching to C, when they decide to go commercial selling RISC hardware for UNIX workstations

- VAX/VMS used Bliss

- Xerox PARC started their research in BCPL, eventually moved to Mesa (later upgraded to Mesa/Cedar), these languages are the inspiration for Wirth's Modula-2 and Oberon languages

- OS/400, nowadays known as IBM i, was developed in PL/S. New code started to be replaced by C++. It was probably the first OS to use a kernel level JIT with a portable bytecode for its executables.

BitSavers and Archive web sites are full of scanned papers and manuals from these and other systems.


Most languages become popular because they have a reputation of necessity. Which is to say, they are popular due to marketing, not due to quality. (As most things are.)


Isn't C just following the syntax of ALGOL? Or are we referring to the parts specific to C?


C is a simpler Algol, yes. It messed up the dangling-else problem, and lost nested procedures, among other things.


It also lost call-by-name parameters, which should be a considered a good thing.




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

Search: