Backend engineer with some self-taught full-stack experience. C/C++, Python, Golang, Typescript. Experience with network visibility and packet processing.
What's with newer languages putting types after variable/function names? Then you need an extra symbol : or -> and a function keyword. It also breaks readability of long function headers as you have to read the name skip to the end to read the return type then back to the first argument. Is there a good reason for this trend?
Well, note that partly due to the way variables and functions are declared in C and C++, parsing those languages (especially C++) is a complete mess.
I think the readability argument is pretty subjective. Personally I find declarations in for instance Rust a lot easier to quickly scan than C++. For one thing the names of functions are all at the same offset, which to me is actually the most important thing. I can see at a glance whether it's a function or variable being declared. I've never found the fact that the return type is at the end to be a problem - why would it be?
The convention dates back to at least ML in the 70s, possibly even longer time back. So it is not some new thing, it's recent rise in popularity is more a reflection in MLs increasing influence in language design space.
If I'd had to guess, the syntax might be inspired by math notation such as x ∈ ℝ
It makes me wonder why C put the ultimate type on the left and not on the right.
C type/variable declarations are an expression that transforms the type/variable into a primitive type, which is then annotated on the left of the expression. Why not on the right?
Because parsers, like humans, read from left to right. Important parsing decisions are usually made as early as possible. An example is recursive descent parsing, which derives its simplicity from making decisions first, allowing a top-down parse. And when humans skim text, I bet it can be shown that it's easier if the syntactically significant locations are aligned near the beginning of each statement.
The intent, as I understand it, is that "declaration should look like use", so that the base type is on the left. If you declare
int *foo;
then
*foo
is an int.
IMHO the existence of "cdecl" is evidence that it might not have been the right choice.
Declaration should look like use is nonsense though. I mean, what is the practical benefit of putting the pointer to the left of the name instead right to the type? For pointers the difference is literally just on which side of the space the asterisk sits at the expensive of making it unreasonably difficult to represent nesting of type constructs.
Some languages use the colon syntax, such as the Pascal family. Others, like Rust and Gleam, use the arrow syntax.
The arrow syntax meshes better with the idea that there's a difference between the types of values, and the meaning of a function signature. "foo: t" declares a name "foo" as having a type "t", but functions are abstractions — what is the "type" of factorial()? It's not "int".
The type of factorial() could be written:
(int) -> int
or just:
int -> int
If you look at the ML family as well as Haskell, that's exactly how they express it.
They do that for other reasons, too; those languages follow lambda calculus, which only has single-argument functions, so all functions are simply mappings between a single value to another value.
I think the C syntax was actually a compromise to simplify the grammar. Remember C dates back to the 60s, and computers had very little RAM and storage back then, so they had to be very clever in how they designed the language. The C function pointer syntax is the way it is because you can reuse the same grammatical rules for parsing types as you do expressions. Pointers are prefix and function calls are suffix.
Because type before name is simply worse in every metrics, hard to parse, hard to omit when infer (change to auto, var, etc), hard to grep for definition (hence the hack <type>\n<name>).
Why do you care about the return type before the name?
If you had never heard about C and its legacy, and were to create your own programming language, would you come up with a syntax like C's?
The structure 'term: definition' is pretty common in many natural languages and has a lot of advantages: all terms are aligned, you can sort them, you can grep the term you're looking for, etc.
I even think it should be extended to functions, too. That 'def' ruins the harmony. Instead of
def factorial(int) -> int
it should be
factorial: fn(int) -> int
You trade a keyword ('def') for another ('fn') but open the way to lambdas (just the part after the colon).
I agree that the -> serves no purpose, it could be made optional. Alternatively one could require the -> and dismiss the 'fn' keyword, like this:
factorial: (int) -> int
It's slightly harder for the parser who has to wait until the -> to understand what it's reading, but it's doable.
About putting the return type after the parameters, that absolutely reflects how I reason about functions: I will want to first examine its input, and then its output. Even the man pages for common functions and commands explain the parameters first, and leave the return value last.
Variable/Parameter names are nicely aligned so there's less scanning to read them. Personally I usually read function arguments before return type, but I can see instances where I'd want to look at return type first. If you're line breaking on parameters for long function signatures, it's not so bad though—the return type will be in a predictable place.
The : and -> are not strictly speaking necessary. Some languages, like go, put the type after the variable name and return type at the end of the function signature without requiring a : or a ->.
Having to always use a colon before the type is better than having to sometimes write "typename" before the type. Not to mention that it makes the code easier to read.
A few years out of college. Would really like to be able to work in python or another modern language, but also have several years of c/c++. Teaching myself full stack dev and recently built a web app that I'm trying launch.
Remote: open to remote
Willing to relocate: maybe
Technologies: C/C++, python, flask, sql, node.js, Networking, wireshark
Résumé/CV: https://github.com/rkblake/Resume/blob/master/randallblake_r...
Email: blakerandall0@gmail.com
Backend engineer with some self-taught full-stack experience. C/C++, Python, Golang, Typescript. Experience with network visibility and packet processing.
reply