It is presented here that name before type is easier to read as a matter of fact. I’m not so sure. In math or languages where type info is optional, we often write “x = 5”. When type info is required, it is natural to evolve to “int x = 5”. Readers would naturally focus on the latter part. When we write “x: int = 5”, the type info is in the middle. We cannot skip it even when we just want to focus on the name and val…
Many languages allow you to elide the type, which is another nice thing about the type following the identifier. In Scala, in particular, types are not the assigned type like in C (where they also serve as the storage specification) -- they are assertions, that the compiler will check are compatible with the code. So `val x: int = "hello"` is no good and the compiler can cut it short right there; this is especially u…
Language Design: Use 'ident: Type' not 'Type ident'
41–50 of 192 posts
Re: Language Design: Use 'ident: Type' not 'Type ident'
#42A more practical reason as a language designer is that C and C++-style type-before-name syntax is a nightmare to lex and parse, as you can't tell whether A * B; is a multiplication or a variable declaration, or whether A D; is a two comparisons with a comma operator or a templated variable declaration, without first knowing the names of all declared types. This means in practice that you have to declare types before…
In 2020, not sure we should care that much about how hard compilers have to work to achieve this. Computers and software are here to support us--we're not here to support them.
Re: Language Design: Use 'ident: Type' not 'Type ident'
#43A more practical reason as a language designer is that C and C++-style type-before-name syntax is a nightmare to lex and parse, as you can't tell whether A * B; is a multiplication or a variable declaration, or whether A D; is a two comparisons with a comma operator or a templated variable declaration, without first knowing the names of all declared types. This means in practice that you have to declare types before…
Declare a local named neko of type Kitten, passing a value to its constructor:
Kitten neko(42);
Declare a local named neko of type Kitten, without passing a value to its constructor: Kitten neko;
Declare a function named neko with zero parameters and with return type Kitten: Kitten neko();
https://en.wikipedia.org/wiki/Most_vexing_parse , https://stackoverflow.com/a/620149/Re: Language Design: Use 'ident: Type' not 'Type ident'
#44It is presented here that name before type is easier to read as a matter of fact. I’m not so sure. In math or languages where type info is optional, we often write “x = 5”. When type info is required, it is natural to evolve to “int x = 5”. Readers would naturally focus on the latter part. When we write “x: int = 5”, the type info is in the middle. We cannot skip it even when we just want to focus on the name and val…
Many languages allow you to elide the type, which is another nice thing about the type following the identifier. In Scala, in particular, types are not the assigned type like in C (where they also serve as the storage specification) -- they are assertions, that the compiler will check are compatible with the code. So `val x: int = "hello"` is no good and the compiler can cut it short right there; this is especially u…
It's also the case that there are plenty of languages where all types imply storage specification and they support plenty of type elision.
Re: Language Design: Use 'ident: Type' not 'Type ident'
#45I disagree. The syntax design should flow from the design of the language itself and whether or not you use prefix or postfix notation for type annotations depends heavily on what makes sense within the semantics of the type system. Design a language before you design a syntax.
Re: Language Design: Use 'ident: Type' not 'Type ident'
#46A more practical reason as a language designer is that C and C++-style type-before-name syntax is a nightmare to lex and parse, as you can't tell whether A * B; is a multiplication or a variable declaration, or whether A D; is a two comparisons with a comma operator or a templated variable declaration, without first knowing the names of all declared types. This means in practice that you have to declare types before…
It's a historical problem in C. Originally, C had only built-in types. Structs were declared with struct foo { int x; int y; }; which is easy to parse. Then came typedef. With user-defined types, foo*bar; isn't parseable with a LALR(1) parser until you've seen the definition of "foo". Even the ordinary case foo bar; needs more than one lookahead to parse. This is a headache for compilers, and a huge headache for anyt…
Rust has made a point of being parser-friendly, to support tooling. The entire reason the turbofish :: exists is to avoid ambiguous grammar. (This operator seems to vex people, I don't get the hate.)
Re: Language Design: Use 'ident: Type' not 'Type ident'
#47Re: Language Design: Use 'ident: Type' not 'Type ident'
#48Earlier quoted context omitted.
>Syntax isn't unimportant #104#101#108#108#111,[Space]world![Space][Space][Tab][Space][Space][Tab][Space][Space][Space][LF] [Tab][LF][Space][Space] [Space][Space][Space][Tab][Tab][Space][Space][Tab][Space][Tab][LF] [Tab][LF][Space][Space] [Space][Space][Space][Tab][Tab][Space][Tab][Tab][Space][Space][LF] [Tab][LF][Space][Space] [Space][Space][Space][Tab][Tab][Space][Tab][Tab][Space][Space][LF] [Tab][LF][Space][Space]…
I didn't say "syntax doesn't matter, pick any ridiculous thing you want". That's what I mean by "not unimportant", though I admit it's not exactly clear that's what I meant. My point is that within the space of reasonable, comprehensible syntaxes, there are no demonstrable differences worth arguing about.
That is a big claim. Is very easy to believe (I do it before, when my knowledge of programming languages was about just 3 or 4. Now is more than 12). :
But is clearly false, and is easy to prove:
async/await
go chan
fn sort(of:list...)
try/catch
match
All the above are just small things that have a HUGE impact in how develop programs. Also, in matter of "small" stuff that could look insignificant: [1, 2, 3] + 1 = [2, 3, 4]
this one is a huge deal in certain niches, also, another "small" and insignificant thing: SELECT ... FROM source
source SELECT ...
All this are just small things. Not all that obvious at the time. Remember how before the times of GOTO the idea of more specialized control flow was unthinkable in the minds of many.Syntax MATTER MOST. Because, is OUR interface. The space of improvement is not super-big, truth, but it impact hugely.
Also, when done correctly, it make the semantics fit like a glove or not.
Another obvious example: Do concurrency whithout syntax help (just using threads). Or performant, safe, concurrency friendly, zero-gc, system-programming, etc without what rust and other langs have bridged.
Re: Language Design: Use 'ident: Type' not 'Type ident'
#49This is also an argument for using keywords of the same length for introducing a variable and a constant. If that’s desirable, it rules out the obvious choices `var` and `const`.
Possibilities include `var` and `val`, which may be too similar-looking, and `var` and `let` - but are people used to (from JavaScript) `let` being mutable? Any other options?
Re: Language Design: Use 'ident: Type' not 'Type ident'
#50A more practical reason as a language designer is that C and C++-style type-before-name syntax is a nightmare to lex and parse, as you can't tell whether A * B; is a multiplication or a variable declaration, or whether A D; is a two comparisons with a comma operator or a templated variable declaration, without first knowing the names of all declared types. This means in practice that you have to declare types before…
Take the first example you've given, and let's just talk about variable declaration:
int* a;
int * a;
int *a;
That's all the same. That's wrong. Obviously, you can write a lexer and parser that doesn't give a crap, but the human mind does. If you think it doesn't, that's only because you've internalized the various cases.It should be this:
int* a;
The type we're talking about is a pointer to a variable of type int: in other words, "a" is an int-pointer. If you were to create a macro, you'd do something like this: #define int_ptr int*
Do you see what I'm getting at? The star in this case is a suffix, equivalent (in our minds) to "_ptr". Conceptually, it doesn't belong anywhere else than attached to the type. It's a compound type, conceptually.Now, take the star being used in a different context:
int b = 10;
int* a = &b;
printf("%d\n", *a);
There, though we see the same character, it's a completely different thing. It's a dereference operator. Conceptually, it belongs attached to the pointer variable it is dereferencing; and since the star is already used in one context as a suffix, here it should be used as a prefix.This is no good:
printf("%d\n", * a);
It doesn't matter that "this compiles." That's not what this is about.Many C programmers (and programmers in other languages, even Python) are used to writing things like this:
int c = x*y;
That's wrong. Sure, the lexer and parser don't care. But that makes the language worse, for the human operator. "But it saves space!" Spare me.The thing with this one example, using the star, is that what we have is the equivalent of a homonym. We have one sign that is actually three different words. Mandating spacing removes the ambiguity you're complaining about.
C is what it is, but if we imagine someone were going to write it today, they should incorporate the above and mandate spacing. For the sake of the humans. "ident type" is not the only solution.