3 ms·
Your original comment said it "is easier to read and understand", not "can be worked out after some practice". Of course it is not like you should inline every
by lifthrasiir 2y ago
Your original comment said it "is easier to read and understand", not "can be worked out after some practice". Of course it is not like you should inline every `typedef`s into a single mess of complicated types, but you never said that you believe only simplest types should be used and C syntax is easier for them.
In any case, I think Go is a clear winner here because all logical types are consecutive tokens. For example `f` in my example is (as you correctly parsed) a pointer to a function that returns an array of 10 integers, but that return type is normally written `int [10]` or `int NAME[10]`, while here is written in two chunks `int` and `[10]` with a big parenthesis inside.
- rramadass 2y agoAgain, my using "is easier to read and understand" was w.r.t. the parent's claim w.r.t. Go's syntax. You understood it wrong to mean an absolute general case. You need practice for complicated things and that is what i was pointing out with "can be worked out after some practice" and not that everything trivial needed practice. "Go is a clear winner here" is your claim and not necessarily one that i agree with since as mentioned, knowing the binding rules and a little practice complicated declarations are not that big of a deal.
- lifthrasiir 2y agoAgreed that it's not actually a big deal (hence "here"), but it does strengthen a point that the C syntax wasn't designed carefully after all. The current C type syntax was completely accidental and any reasonable design could have avoided that. If that was too late for some reason, one could have defined a new parallel syntax that solves this problem. In fact C++ did so via its new function declaration syntax `auto f(...) -> ...`. Guess why...
- rramadass 2y ago> The current C type syntax was completely accidental and any reasonable design could have avoided that. Absolutely baseless claim. The C syntax and language is the product of a small group (not a committee) of smart people with the goals of syntactical brevity, close to machine architecture (PDP-7/11) and the design goal of building along the path of BCPL->B->C. Dennis Ritchie himself explains the rationale in his paper The Development of the C Language and so one does not need to make untenable assumptions. The enduring success of the language (even in the face of all the developments since then in Computer HW and PLT) is proof of the validity of its design goals. Its "Abstract Machine" is simple and there is no complicated Object Model with the syntax merely being a thin veneer over a sequence of bytes. Contrast it with most modern languages (which seem to be designed to solve world peace/hunger and everything in between) and C appears more and more relevant these days. C++ used judiciously without a lot of "new features" introduced by the standards committee (the bane of the language) takes it to the next level sweet spot.
- lifthrasiir 2y agoNot exactly, read the exact paragraph in The Development of the C Language: > [...] In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration. > The scheme of type composition adopted by C owes considerable debt to Algol 68, although it did not, perhaps, emerge in a form that Algol's adherents would approve of. The central notion I captured from Algol was a type structure based on atomic types (including structures), composed into arrays, pointers (references), and functions (procedures). Algol 68's concept of unions and casts also had an influence that appeared later. Algol 68 by the way had a sensible type syntax that is akin to Go's. Ritchie "explains" the syntax difference by having the same syntax for the type and the expression, but that's not exactly why. For example there are actually two expressions relevant here, `*` dereference and `&` reference. Why was the former used? Why couldn't `*` be made a postfix at this point if the same syntax was a big concern? Ritchie himself never fully elaborated on those points, and I think that's because it was never his primary concern at all. As you have noted, it is very important to realize that C did have their design goals (for which C did a very excellent job). On the other hand it would be very misleading to claim that C had some bigger visions even at that time and they validate its design! Ritchie and others were clearly smart but they didn't design C to be something magnificant, it was a rough product from various trade-offs they had to endure. So why this particular syntax? Well, because B already picked a prefix `*` which Ritchie didn't want to change at all, and he allowed it to infect all other aspects of the type syntax without much consideration. (Or more neutrally, Ritchie couldn't figure out any other option when he had to keep the B compatibility. But keep in mind that B have already changed that operator from BCPL.) Technically speaking it was somehow designed, but only by following the path of the least resistance, not a solid reasoning, hence my use of the word "accidental". There are many other examples, such as the logical `&` (etc.) being renamed to `&&` but the bitwise `&` keeping the original precedence order because nothing was done. To be fair to Ritchie though, it is not his fault, but rather a fault of the whole software community that was fixated on this ancient language designed for specific purposes way too long.
- rramadass 2y agoThe relevant paragraphs from Ritchie's paper are not just what you quoted (much of your comment is not relevant) but much more; For each object of such a composed type, there was already a way to mention the underlying object: index the array, call the function, use the indirection operator on the pointer. Analogical reasoning led to a declaration syntax for names mirroring that of the expression syntax in which the names typically appear. Thus, int i, *pi, **ppi; declare an integer, a pointer to an integer, a pointer to a pointer to an integer. The syntax of these declarations reflects the observation that i, pi, and ppi all yield an int type when used in an expression. Similarly, int f(), *f(), (*f)(); declare a function returning an integer, a function returning a pointer to an integer, a pointer to a function returning an integer; int *api[10], (*pai)[10]; declare an array of pointers to integers, and a pointer to an array of integers. In all these cases the declaration of a variable resembles its usage in an expression whose type is the one named at the head of the declaration. The above can be summarized as the following two points; 1) "Declaration reflects Use" (from K&R C book) which leads us to the corollary, 2) Syntax is variable-centric rather than type-centric i.e. You look at how the variable is supposed to be used and then work out its type. > To be fair to Ritchie though, it is not his fault, but rather a fault of the whole software community that was fixated on this ancient language designed for specific purposes way too long. Again, this is completely baseless and merely your opinion. I have already pointed out the main design goals which drove its design and the fact that it is still relevant today is proof of that. The "simplicity" of its very design is its greatest strength. The fact that modern needs (eg. Strong Type Safety, Multi-paradigm, Security, Concurrency etc.) require us to design/seek out more language features is not a reflection on the language itself since it was designed well before these "wants" became "needs". On the other hand the various extensions of C (eg. Objective-C, Concurrent-C, Handel-C etc.) are proof of its versatility and extensibility and hence its enduring relevance.