Hacker News new | ask | show | jobs
by exitcode00 2727 days ago
How about just using Ada? It has the added bonus of not being a gimmick (depending on who you ask I suppose ; )

Ada: type Ret_Typ is array (1..3) of Integer; Foo : access function return not null access Ret_Typ := null;

C: int ((foo)(const void *))[3]

Cdecl: declare foo as pointer to function (pointer to const void) returning pointer to array 3 of int

2 comments

In the interest of furthering annoying language smuggery, the rough Rust equivalent:

    foo: fn() -> Box<[i32; 3]>
Alternately, if the pointer is into static memory and not something allocated on the heap:

    foo: fn() -> &'static <[i32; 3]>;
That's pretty nice to look at and not too hard to read. In my opinion, for commonly used syntax (like fn decls), some well-chosen punctuation marks (', ->, :, in this case) are often boon to readability compared to keywords. So I think the Rust syntax in this case is nicer than Ada's.

But in any case, while complicated C declarations may be uglier and take more effort to read than those in other languages, they are at least tractable once you learn the trick of "declaration follows use" and working backwards as GP describes.

Separately, though, what do you mean by your "gimmick" comment?

> Separately, though, what do you mean by your "gimmick" comment?

Just meaning the website CDecl - its a neat tool to make C readable in English, but Ada is a real language used to make planes fly etc. Many people have contempt for it though which is why I made the joke xD

Interesting that you can note which type of memory an anonymous type comes from in Rust. I suppose its for optimization purposes? Doesn't seem that helpful from a pure typing perspective.

As an aside I doubt a layman would be able to understand that notation in Rust, whereas my girlfriend might be able to grasp or read Ada code or the output of CDecl.

> Alternately, if the pointer is into static memory and not something allocated on the heap

There's really no need to box a 12-bytes array in the first place.

I'm not defending C's syntax as sane here, because it's not. It boils down to have two problems:

1. The syntax isn't "type id, id, id;", it's "type expr, expr, expr;" The trend for C-style languages have been to move to the former type syntax, so C/C++ is the anomaly here.

2. Pointer declarators show up to the left of the name while function and array declarators show up to the right of the name. This means you can't figure out the type by scanning in one direction. Contrast this with LLVM, where function arguments and pointer types both go to the right of the leaf type (while arrays are infix), or Rust, where they both live on the left of the leaf type.

Reading for both ends is maddening for seasoned devs, but in a general sense most languages are symbol salads these days for arbitrary, subjective reasons. The decisions made during the C development to squeeze the juice out of 60 character wide terminals haunt us to this day... like case sensitivity
> like case sensitivity

What's wrong with case sensitivity?

Sure the current doctrine of programming says its good, but lets take a step back. First of all its counter intuitive to writing English and it damages readability so you may have naming conflicts without realizing it or the compiler being able to warn you.

Also, in addition to remembering what a function is called you have to also remember its casing which different libraries may want to be phrased differently (like C libraries versus C++ libraries).

Bypassing the very real issues it may cause in the design of your software it also may lead to silly library cruft (see Java's Color class) - how many ways can you spell blue?

https://docs.oracle.com/javase/7/docs/api/java/awt/Color.htm...

Case-sensitivity is, more or less, a default: you have different strings that have distinct encodings, so you treat them as different identifiers.

The alternative to case-sensitivity requires your compiler to know about case, and, more importantly, how to do case-folding. At that point, you can either choose to (a) restrict identifiers to a Some (probably ASCII) limited subset of characters, (b) only make some subset of acceptable characters (reliably) case-insensitive, (c) require every compiler to have tables for case-folding.

That's before we get into the locale-dependence of case-folding, which makes the letter "i" unreliable.

And you still have to distinguish Color and Colour.

It is actually possible to define all of those things in a compiler standard and force them to do it certain ways or document possible "implementation permissions", but, again unicode identifiers are rare in practice because programming is designed for English speakers like it or not.

http://www.ada-auth.org/standards/2xaarm/html/AA-2-3.html

> And you still have to distinguish Color and Colour.

Still have to do that with case sensitive langs - whats the point here?

Case insensitivity sounds good except it quickly runs afoul of "language isn't so simple."

If I define a variable as "groß", does "GROSS" or "GROẞ" match it (or both, which probably implies "gross" would match as well)? What about "ê" and "E"? Or the infamous i/I/İ/ı debacle, which could make matching "insane" to "INSANE" locale-dependent? How do you define case-insensitivity in a way that makes sense?

These are solved problems though and unicode identifiers are rare in practice...

See Normalization Form KC and Clause 21 of ISO/IEC 10646:2017.

"Normalization forms are the mechanisms allowing the selection of a unique coded representation among alternative; but equivalent coded text representations of the same text. Normalization forms for use with ISO/IEC 10646 are specified in the Unicode Standard UAX#15..." yada yada