The is/as pair seems like a tremendous improvement to the dismal C++ type inspection and casting status quo.
However I'm a bit suspect of language syntax that superficially appeals to plain-English meaning of contrasting words, but adds a cognitive overload. I'm thinking of how JavaScript has both `for...in` and `for...of` — the everyday usage of the "in" and "of" prepositions provides no guidance to what these words mean in JavaScript iteration.
The mnemonic I use is "for index", as in for keys you can use to index things. One gotcha to remember here is that officially all property names are strings [0], and that includes array indexes. To exemplify, `for (let x in { a: 40, b: 41, c: 42 }) { console.log(x); }` would give you "a", "b", "c" as that's what you can use as an index to key into that object to get the values. And `for (let x in [40, 41, 42]) { console.log(x); }` would give you "0", "1", "2" as that what's you can use as an index to key into that object. I always remember `for..of` as just the other one.
The trick is to remember that “for in” is the obvious one, meaning it’s the older one, meaning it’s the one that’s next to useless and should almost never be used.
In "The C++ Programming Language", casting is described as a tool of last resort. Bjarne says he likes long winded cast operators because they stand out as an easily greppable marker of complex code. I wonder if this perception is changing.
Personally I like the explicit names, even if I can appreciate the argument that the proposed mechanism makes the templating system more generic.
> In general, you should know what objects you are sending and receiving, and it shouldn’t be a mystery that requires reinterpreting
You should know what's the interface that you're sending/receiving, but if you're planning on making downcasts then either you're doing something very exotic or you should take a step back and reevaluate what you're doing.
I'm seeing a lot of people in this thread complaining about features being added to C++ that improve developer experience, but barely anyone complaining that shooting yourself in the foot requires making intentional choices to get your feet in front of your guns.
In school I learned about inheritance, not composition. The usual: base "shape" class, then subclasses triangle, square, circle, etc. Then you can have a collection of "shape"s that know what they are. What I've read online indicates it's the same for most other people (who learned in a formal context, anyway). This way of doing things necessitates downcasting; at some point you're converting shape into a triangle or whatever, to access some specific method it has.
I'm not saying this is the right way of doing things (I don't think so), but many people expect this to be possible to do easily -- and it isn't. For them this is normal and not "something very exotic". I guess this is the source of the misunderstanding and the complaints.
> In school I learned about inheritance, not composition.
And that's perfectly fine, provided that students learn that trying to do downcasts like casting an animal instance to a dog instance is something that in general never made any sense, and more often than not reflects ignorance.
> This way of doing things necessitates downcasting;
Not true. That way of doing things necessitates ignorance of basic concepts across many domains, including basic OO programming in general and C++ in particular. You can't blame the tool of your choice for problems you create out of ignorance and failing to think things through.
> In "The C++ Programming Language", casting is described as a tool of last resort. Bjarne says he likes long winded cast operators because they stand out as an easily greppable marker of complex code.
The idea makes a lot of sense. Casting shouldn't be necessary at any time as this means you leave the safe space a static type-system gives you. At the point when you cast all bets are off; it's only on you to prevent type errors, the compiler can't help any more (ant this property of casts is frankly "viral", so it can affect code far away).
The problem with C++ is of course that they have a gazilion of ways to do (sometimes in surprising ways almost) exactly the same.
In Scala for example casts are also very explicit. You need to call the `.asInstanceOf[TargetType]` method. But that's the only syntax for this.
It makes really a big difference to have only one obvious way to do something. (Frankly Scala also doesn't always shine everywhere in this regard).
Its a bit like saying glue and nails isn't necessary to build a house. You should be able to do everything with precision joinery! Many times we are doing a renovation where a good portion makes it impossible to do precision joinery.
> The is/as pair seems like a tremendous improvement to the dismal C++ type inspection and casting status quo.
No, unfortunately, it further complicates C++, because the original ways of expressing the same thing will not be removed. You'll just need to remember another level of sugar, but must not forget the lower levels -- e.g., if you want to extend your own type to work with this, you'll need to provide the right plugin definitions. I was especially appalled by the 'x.get()' and 'x.value()' equivalences -- this is just a layer of obfuscation.
That table Herb provides will be added to C++ -- but nothing will be removed.
> No, unfortunately, it further complicates C++, because the original ways of expressing the same thing will not be removed.
This is a very unwise and shortsighted take. Not deprecating features right away means everyone's life is made easier as you can upgrade manage full/partial project upgrades to newer C++ standards without having to resort to tickets blocking your critical path with all-or-nothing upgrades.
And this does not stop at your projects. Dependencies are also covered. Do you believe it's in your best interests that you lose your ability to up point releases to your
Lastly, why does it bother you that backwards compatibility is a Hallmark of C++, and deprecation is a multi-standard process? You're free to stick to a subset if that's what you want. What's the point of getting all bothered with being able to continue using features without seeing them break under your nose for no reason other than a version bump?
Not GP, but what bothers me is that this attitude does not take into account what most cpp programmers actually end up doing: Unless there's somebody at the top of the organization that can set the "right" rules at the start of the project, a novice won't know to use the "right" feature. And neither will somebody who comes from other cpp projects that only had the old way of doing things. The result: a codebase with every possible way of doing a thing, which is strictly worse than one where only one way is used, even if it's not the prettiest. Now if you want to work on it you need to know about everything. Every new feature just increases the need for overhead knowledge. It's almost unavoidable.
So, complaining about this would be an unwise shortsighted take in other languages maybe, that don't have the proven track record of just leaving 10 different ways of doing the same thing on the standard. In cpp it's just the voice of somebody who has been burned one too many times by that kind of feature optimism.
> Not GP, but what bothers me is that this attitude does not take into account what most cpp programmers actually end up doing: Unless there's somebody at the top of the organization that can set the "right" rules at the start of the project, a novice won't know to use the "right" feature.
Unless we're discussing single-developer projects, you'd be hard-pressed to find a single project that does not employ any sort of code reviews,where more seasoned developers have a say in each and every change that's proposed.
If a project is manned by inexperienced novices, the language is not to blame for the developer's regrettable choices.
> The result: a codebase with every possible way of doing a thing, which is strictly worse than one where only one way is used, even if it's not the prettiest.
This is outright incompetence, as it violates basic software engineering principles like the principle of least surprise.
If a project repeatedly surprised developers with multiple fancy ways of doing the same thing and developers don't put time aside to fix that, the tech stack in use is not a factor in this problem.
JavaScript's for in/of were not intended to be like that. `in` is broken so in a world without backwards compatibility to worry about they would have just fixed it to have the behaviour of `of`. But because they had to consider backwards compatibility they had to come up with a new name.
You should basically never use `for in`. I guess part of the problem is that making that clear in most languages is easy - just add a compiler warning. But JavaScript requires users to manually set up and configure ESLint and if you know how to do that you probably already know not to use `for in` anyway.
I guess modern runtimes like Deno might help here.
What is broken about for in? A quick search didn't turn up anything for me. I don't write much Javascript but for the times I do this seems like it could be useful information for me.
That talks about using for…in with arrays, but not plain objects. IMO it’s fine for iterating over object keys.
Sure, there are bizarre ways to make your objects go nuts in JavaScript through prototypal inheritance, but if you’re doing that then for…in is not your biggest problem.
You shouldn't normally need to iterate over object keys. Doing so is a pretty big indication of bad design. If you do you should use `Object.entries()` which avoids enumerating properties in the prototype chain.
There's really no reason at all to use for-in and its use is usually a mistake.
This is weird advice IMHO. It seems like you’re saying that iterating over dictionary keys is bad in general, not just in JavaScript. Doesn’t make any sense to me.
> the highest level--the root--of the [Unix] filesystem is always designated with the single character "/" and it always contains the same set of top-level directories [...] Note the obsessive use of abbreviations and avoidance of capital letters; this is a system invented by people to whom repetitive stress disorder is what black lung is to miners. Long names get worn down to three-letter nubbins, like stones smoothed by a river.
-- Neal Stephenson, In The Beginning... Was The Command Line, 1999
But also note that sometimes the people who make these decisions later realise that they went too far:
> Ken Thompson was once asked what he would do differently if he were redesigning the UNIX system. His reply: "I'd spell creat with an e."
-- Kernighan & Pike, The UNIX Programming Environment, 1984
If Caesar can hide the sun from us with a blanket, or
put the moon in his pocket, we will pay him tribute
for light; else, sir, no more tribute, pray you now.
If / else is perfectly clear and correct grammar, though we don't use it in modern speech. We've not chosen 'otherwise', else we waste five columns to no end.
Herb mentions the possibility of `is void` generalizing across pointers, std::optional, and std::future. This seems like it could create ambiguity with a future<void> wherein a non-ready future<void> `is void` and also a ready future<void> `is void`. How should it be handled, I wonder?
Seems to me like a future<void> that can safely be dereferenced is ready and not void itself. That the data type can point to a void doesn't really matter it seems, just that the pointer itself isn't null. Essentially, is void seems to be a null check that works for more types.
> is std::nullopt_t doesn’t appear to match an empty optional
> that this wasn’t supported [...] was intentional
This is a very C++y thing to do. "Wanna do that thing? Well, the way that is obvious works, compiles, but doesn't do what it should. <good reasons why>. Sorry!"
I am rather parsimonious with vertical whitespace (can't stand { on its own line, for example) but I use a lot of horizontal whitespace, and would thus write this
operator , ();
Not that I have ever overloaded the comma operator, which anyway only exists because of C's (well, Algol's) foolish distinction between expressions and statements.
I was initially thrown by the example code which doesn't look like C++ at all:
main: () -> int = { ... }
I learned this is 'Cpp2' which was also discussed by Herb Sutter recently[0]. I don't know if there is a desire for C++ (i.e. Cpp1) to become Cpp2 at some point - could this ever happen?
No, the idea is to build a 'bubble' of new code that isn't subject to all the backwards-compatible flaws of the old syntax. It's just an experiment for now.
If I understand the cpp2 pitch correctly, you should be able to embed cpp2 functions inside preexisting C++ source files, so it's more like the old cppfront compiler (C++ supports basically C syntax in C++ files) than a fully transpiled syntax.
Frankly, I hope I'm out of the C++ eco-system by then.
Speaking of the "desire[s] for [of] C++", it's a matter of design-by-committee and we all know what sort of results this brings. Consultants love each new standard. I am happy about this, that or that other library improvement but I'd wish they'd stop fucking about with the language. Come on guys, you aren't ever going to catch up to ML or lisp or ever return to C's "dirty elegance". Just stop breaking the mental model users have of C++ with every update please?
Sorry that comment went nowhere, I'm massively frustrated with C++, its direction, and I can't wait to leave it behind for good.
But "could this ever happen?" the committee agrees on the wildest stuff, so, sure, why not.
> Sorry that comment went nowhere, I'm massively frustrated with C++, its direction, and I can't wait to leave it behind for good.
I fail to see how a "direction" of a language like C++ is of any concern to professional C++ developers. Most of C++ projects are stuck in C++14 or C++11. Projects are only migrated to newer C++ standards if there are very compelling reasons to do so. If a newer standard offers no value, projects simply don't migrated.
Lastly, why do people feel that perpetuating the C++ label is important? Those who pick the right tool for the job don't play favorites.
> I don't know if there is a desire for C++ (i.e. Cpp1) to become Cpp2 at some point - could this ever happen?
On the balance, I think most of the committee is weakly against some of these syntax changes. From what I've heard, the push for uniform initialization in C++11 was seen as a mistake in retrospect, and the more recent effort to push uniform call syntax wasn't popular enough to pursue further.
"is" is the reference equality operator, that can't be overloaded, in Python. It having a different meaning in C++ is unfortunate. "is" seems to really mean "is a" in C++. instanceof / isinstance has a related meaning in Java or JavaScript / Python and is a way more clear keyword than "is", which is a very ambiguous word.
Coming from python, the meaning of this "is" is effectively "is" or "issubclass" for types and "isinstance" for value,type pairs. It's really not that much of a stretch. I'd question of C++ really needs to care what Python devs are going to think, though.
Would it care about devs using multiple languages, switching back and forth, or people coming to C++ from other languages though?
Of course program language designers need to care about the ergonomics of their languages, and how it sits in the bigger ecosystem, it's their job. If they only target experts specialized in one language who don't practice other languages, that's just wrong if you ask me.
I was just suggesting a potential source of confusion, saying it's unfortunate. Not that this is wrong or anything.
Now, someone pointed out that C# does the same thing with "is" and "as" (which I didn't know, I don't know C#) so it seems they did take inspiration from the ecosystem and did not invent a potentially confusing language construct alone. That does not remove the confusion, but it's actually good they took the same syntax for a feature that already exists in the neighborhood.
> Would it care about devs using multiple languages, switching back and forth, or people coming to C++ from other languages though?
I'm not sure where we'd draw the line, and "nobody can reuse a reserved word that any other language uses unless they're conceptually identical" seems completely misguided. If you're using multiple langues and switching back and forth, it's your responsibility to know those languages. I use 5 languages frequently, "switching" at least several times per day. I'm a grayhair, so maybe I'm taking my experience for granted, but this seems like an unreasonable burden to put on language designers.
> and "nobody can reuse a reserved word that any other language uses unless they're conceptually identical" seems completely misguided
I agree with this, and this would be far away from what I stated (that the "collision" is unfortunate).
> If you're using multiple langues and switching back and forth, it's your responsibility to know those languages
Absolutely, but we are human beings, we make mistakes, confusions are source of mistakes. This is perhaps unavoidable, and maybe using "is" what the best decision despite this, but still unfortunate. Maybe Python created this confusion in the first place, if Delphi had "is", with a meaning close to the C++ one.
If your mental model of C++ is viewing everything as implicit references like Python, this operator is the least of your problems. If you are not viewing C++ that way, there is no way you could confuse the two operators, because the Python one would make little sense in C++.
Just to be clear, risking of stating the obvious, when I wrote "overloaded", I was talking about operator overloading.
In both C++ and Python, == can be overloaded, so if you need to be sure you are not dealing with an overloaded equality, "is" is convenient in Python. I'm not sure what I would do in C++, and I could imagine a world where "is" in C++ was like "==", but guaranteed to not be overloaded.
Just to be clear: “to be” refers to the English language (no “to be” operator or this and that in programming). “Overloaded” means that it can mean a whole bunch of different things. This should be obvious from context.
Yes, I understood your comment. It's just that since you used the same word as me but with a different meaning, I wanted to make sure there was no misunderstanding.
Am I the only one that really dislikes the Cpp2 syntax? I get it's coming from a Rust influence, but it just feel much harder to parse by humans.
The way a function is declares looks just like a variable assignment for instance, but in a compiled language it pushes the wrong paradigm on me, since that's pretty much immutable.
I must admit that I'm mostly writing Python and JS these days, but the way the colon is being used feels grossly inconsistent and confusing. Why not say std.vector for instance now instead of std::vector?)
> The way a function is declares looks just like a variable assignment for instance, but in a compiled language it pushes the wrong paradigm on me, since that's pretty much immutable.
I think one of the problems with the syntax is that colon (ordinary used for type ascription in ML-family languages) is being used for... something else. For example, in
foo: (x: int) -> int = (expression using x)
the introduction of the 'x' binding is in the type position of 'foo', whereas in OCaml it would be
let foo (x: int): int = ...
Here the binding of 'x' is associated to 'foo' rather than first appearing in type position. I think this is more readable, and the component parts are more easily parsed by humans. One could argue that visually, using an arrow as in
let foo (x: int) -> int = ...
is more readable, but the OCaml syntax captures the fact that the RHS of the binding is defining an 'int' rather than a function value.
> I must admit that I'm mostly writing Python and JS these days, but the way the colon is being used feels grossly inconsistent and confusing. Why not say std.vector for instance now instead of std::vector?)
One potential sensible distinction would be to use one for statically determined paths and the other for dynamically determined paths (including the separate dynamic phase of compile-time constexpr evaluation).
> the RHS of the binding is defining an 'int' rather than a function value
But what's the difference between an `int` value and a function value? It's only the type!
I don't know Cpp2, need to have a closer look, but treating everything as a value makes perfect sense, imho, as everything is just a value in the end.
Any definition will become some structure in memory eventually. A "program", and a function is nothing else than a "small program", is data. Only the interpretation of said data makes the difference.
Types hint at how some data is meant to be interpreted. You could say they determine the interpreter to use, later on.
A syntax that makes those basic ideas very clear seems therefore very convincing to me. It's imho less confusing than something that does treat some "special" types of data, namely function values, very differently even on the syntax level, although the only difference is the type (which is the hint at how this data should be interpreted and nothing more).
Even an `int` value can be "executed", so there is no fundamental difference to the idea of a "function". Just interpret the `int` as a pointer to memory. The machine doesn't care as it allows arbitrary interpretations of arbitrary data structures. That's the whole point of a programmable computer in fact. (And also the constant source of the security issues with them).
As a Rust programmer it doesn't look like Rust influence to me. Rust would have "introducer keywords" here so that we know what we're doing e.g. fn is a function, let is a variable declaration, const is a constant definition ...
62 comments
[ 3.6 ms ] story [ 125 ms ] threadHowever I'm a bit suspect of language syntax that superficially appeals to plain-English meaning of contrasting words, but adds a cognitive overload. I'm thinking of how JavaScript has both `for...in` and `for...of` — the everyday usage of the "in" and "of" prepositions provides no guidance to what these words mean in JavaScript iteration.
[0] https://stackoverflow.com/q/27537677/1470607
Personally I like the explicit names, even if I can appreciate the argument that the proposed mechanism makes the templating system more generic.
You should know what's the interface that you're sending/receiving, but if you're planning on making downcasts then either you're doing something very exotic or you should take a step back and reevaluate what you're doing.
I'm seeing a lot of people in this thread complaining about features being added to C++ that improve developer experience, but barely anyone complaining that shooting yourself in the foot requires making intentional choices to get your feet in front of your guns.
I'm not saying this is the right way of doing things (I don't think so), but many people expect this to be possible to do easily -- and it isn't. For them this is normal and not "something very exotic". I guess this is the source of the misunderstanding and the complaints.
And that's perfectly fine, provided that students learn that trying to do downcasts like casting an animal instance to a dog instance is something that in general never made any sense, and more often than not reflects ignorance.
> This way of doing things necessitates downcasting;
Not true. That way of doing things necessitates ignorance of basic concepts across many domains, including basic OO programming in general and C++ in particular. You can't blame the tool of your choice for problems you create out of ignorance and failing to think things through.
The idea makes a lot of sense. Casting shouldn't be necessary at any time as this means you leave the safe space a static type-system gives you. At the point when you cast all bets are off; it's only on you to prevent type errors, the compiler can't help any more (ant this property of casts is frankly "viral", so it can affect code far away).
The problem with C++ is of course that they have a gazilion of ways to do (sometimes in surprising ways almost) exactly the same.
In Scala for example casts are also very explicit. You need to call the `.asInstanceOf[TargetType]` method. But that's the only syntax for this.
It makes really a big difference to have only one obvious way to do something. (Frankly Scala also doesn't always shine everywhere in this regard).
No, unfortunately, it further complicates C++, because the original ways of expressing the same thing will not be removed. You'll just need to remember another level of sugar, but must not forget the lower levels -- e.g., if you want to extend your own type to work with this, you'll need to provide the right plugin definitions. I was especially appalled by the 'x.get()' and 'x.value()' equivalences -- this is just a layer of obfuscation.
That table Herb provides will be added to C++ -- but nothing will be removed.
This is a very unwise and shortsighted take. Not deprecating features right away means everyone's life is made easier as you can upgrade manage full/partial project upgrades to newer C++ standards without having to resort to tickets blocking your critical path with all-or-nothing upgrades.
And this does not stop at your projects. Dependencies are also covered. Do you believe it's in your best interests that you lose your ability to up point releases to your
Lastly, why does it bother you that backwards compatibility is a Hallmark of C++, and deprecation is a multi-standard process? You're free to stick to a subset if that's what you want. What's the point of getting all bothered with being able to continue using features without seeing them break under your nose for no reason other than a version bump?
So, complaining about this would be an unwise shortsighted take in other languages maybe, that don't have the proven track record of just leaving 10 different ways of doing the same thing on the standard. In cpp it's just the voice of somebody who has been burned one too many times by that kind of feature optimism.
Unless we're discussing single-developer projects, you'd be hard-pressed to find a single project that does not employ any sort of code reviews,where more seasoned developers have a say in each and every change that's proposed.
If a project is manned by inexperienced novices, the language is not to blame for the developer's regrettable choices.
> The result: a codebase with every possible way of doing a thing, which is strictly worse than one where only one way is used, even if it's not the prettiest.
This is outright incompetence, as it violates basic software engineering principles like the principle of least surprise.
If a project repeatedly surprised developers with multiple fancy ways of doing the same thing and developers don't put time aside to fix that, the tech stack in use is not a factor in this problem.
You should basically never use `for in`. I guess part of the problem is that making that clear in most languages is easy - just add a compiler warning. But JavaScript requires users to manually set up and configure ESLint and if you know how to do that you probably already know not to use `for in` anyway.
I guess modern runtimes like Deno might help here.
Sure, there are bizarre ways to make your objects go nuts in JavaScript through prototypal inheritance, but if you’re doing that then for…in is not your biggest problem.
There's really no reason at all to use for-in and its use is usually a mistake.
-- Neal Stephenson, In The Beginning... Was The Command Line, 1999
But also note that sometimes the people who make these decisions later realise that they went too far:
> Ken Thompson was once asked what he would do differently if he were redesigning the UNIX system. His reply: "I'd spell creat with an e."
-- Kernighan & Pike, The UNIX Programming Environment, 1984
A quote from Shakespeare's Cybeline:
If / else is perfectly clear and correct grammar, though we don't use it in modern speech. We've not chosen 'otherwise', else we waste five columns to no end.> that this wasn’t supported [...] was intentional
This is a very C++y thing to do. "Wanna do that thing? Well, the way that is obvious works, compiles, but doesn't do what it should. <good reasons why>. Sorry!"
I like it, it's job security.
https://fouronnes.github.io/cppiceberg/
Hah, wow.
[0]: https://herbsutter.com/tag/cpp2/
Speaking of the "desire[s] for [of] C++", it's a matter of design-by-committee and we all know what sort of results this brings. Consultants love each new standard. I am happy about this, that or that other library improvement but I'd wish they'd stop fucking about with the language. Come on guys, you aren't ever going to catch up to ML or lisp or ever return to C's "dirty elegance". Just stop breaking the mental model users have of C++ with every update please?
Sorry that comment went nowhere, I'm massively frustrated with C++, its direction, and I can't wait to leave it behind for good.
But "could this ever happen?" the committee agrees on the wildest stuff, so, sure, why not.
I fail to see how a "direction" of a language like C++ is of any concern to professional C++ developers. Most of C++ projects are stuck in C++14 or C++11. Projects are only migrated to newer C++ standards if there are very compelling reasons to do so. If a newer standard offers no value, projects simply don't migrated.
Lastly, why do people feel that perpetuating the C++ label is important? Those who pick the right tool for the job don't play favorites.
On the balance, I think most of the committee is weakly against some of these syntax changes. From what I've heard, the push for uniform initialization in C++11 was seen as a mistake in retrospect, and the more recent effort to push uniform call syntax wasn't popular enough to pursue further.
Of course program language designers need to care about the ergonomics of their languages, and how it sits in the bigger ecosystem, it's their job. If they only target experts specialized in one language who don't practice other languages, that's just wrong if you ask me.
I was just suggesting a potential source of confusion, saying it's unfortunate. Not that this is wrong or anything.
Now, someone pointed out that C# does the same thing with "is" and "as" (which I didn't know, I don't know C#) so it seems they did take inspiration from the ecosystem and did not invent a potentially confusing language construct alone. That does not remove the confusion, but it's actually good they took the same syntax for a feature that already exists in the neighborhood.
I'm not sure where we'd draw the line, and "nobody can reuse a reserved word that any other language uses unless they're conceptually identical" seems completely misguided. If you're using multiple langues and switching back and forth, it's your responsibility to know those languages. I use 5 languages frequently, "switching" at least several times per day. I'm a grayhair, so maybe I'm taking my experience for granted, but this seems like an unreasonable burden to put on language designers.
I agree with this, and this would be far away from what I stated (that the "collision" is unfortunate).
> If you're using multiple langues and switching back and forth, it's your responsibility to know those languages
Absolutely, but we are human beings, we make mistakes, confusions are source of mistakes. This is perhaps unavoidable, and maybe using "is" what the best decision despite this, but still unfortunate. Maybe Python created this confusion in the first place, if Delphi had "is", with a meaning close to the C++ one.
In both C++ and Python, == can be overloaded, so if you need to be sure you are not dealing with an overloaded equality, "is" is convenient in Python. I'm not sure what I would do in C++, and I could imagine a world where "is" in C++ was like "==", but guaranteed to not be overloaded.
Of course, Python can't reserve "to be".
Yes, I understood your comment. It's just that since you used the same word as me but with a different meaning, I wanted to make sure there was no misunderstanding.
The way a function is declares looks just like a variable assignment for instance, but in a compiled language it pushes the wrong paradigm on me, since that's pretty much immutable.
I must admit that I'm mostly writing Python and JS these days, but the way the colon is being used feels grossly inconsistent and confusing. Why not say std.vector for instance now instead of std::vector?)
I think one of the problems with the syntax is that colon (ordinary used for type ascription in ML-family languages) is being used for... something else. For example, in
the introduction of the 'x' binding is in the type position of 'foo', whereas in OCaml it would be Here the binding of 'x' is associated to 'foo' rather than first appearing in type position. I think this is more readable, and the component parts are more easily parsed by humans. One could argue that visually, using an arrow as in is more readable, but the OCaml syntax captures the fact that the RHS of the binding is defining an 'int' rather than a function value.> I must admit that I'm mostly writing Python and JS these days, but the way the colon is being used feels grossly inconsistent and confusing. Why not say std.vector for instance now instead of std::vector?)
One potential sensible distinction would be to use one for statically determined paths and the other for dynamically determined paths (including the separate dynamic phase of compile-time constexpr evaluation).
But what's the difference between an `int` value and a function value? It's only the type!
I don't know Cpp2, need to have a closer look, but treating everything as a value makes perfect sense, imho, as everything is just a value in the end.
Any definition will become some structure in memory eventually. A "program", and a function is nothing else than a "small program", is data. Only the interpretation of said data makes the difference.
Types hint at how some data is meant to be interpreted. You could say they determine the interpreter to use, later on.
A syntax that makes those basic ideas very clear seems therefore very convincing to me. It's imho less confusing than something that does treat some "special" types of data, namely function values, very differently even on the syntax level, although the only difference is the type (which is the hint at how this data should be interpreted and nothing more).
Even an `int` value can be "executed", so there is no fundamental difference to the idea of a "function". Just interpret the `int` as a pointer to memory. The machine doesn't care as it allows arbitrary interpretations of arbitrary data structures. That's the whole point of a programmable computer in fact. (And also the constant source of the security issues with them).
https://dlang.org/spec/expression.html#is_expression