Something I implemented today: “is void”
herbsutter.com
herbsutter.com
> 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.
Hah, wow.
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.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.
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 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.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
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).
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).
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? auto main() -> int { ... }
in actual C++, which is not very far off.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.